From a1be57453908011353c927cafa0b94814eaed973 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Thu, 18 Jun 2020 12:47:48 +0200 Subject: [PATCH] Fix #3314 - GBXML translate spaces and stuff even if Facility and/or Building aren't isntantianted --- src/gbxml/ForwardTranslator.cpp | 90 ++++++++++++++++++--------------- src/gbxml/ForwardTranslator.hpp | 8 ++- 2 files changed, 56 insertions(+), 42 deletions(-) diff --git a/src/gbxml/ForwardTranslator.cpp b/src/gbxml/ForwardTranslator.cpp index 7d20b3457cb..d016176b5bb 100644 --- a/src/gbxml/ForwardTranslator.cpp +++ b/src/gbxml/ForwardTranslator.cpp @@ -188,10 +188,9 @@ namespace gbxml { gbXMLElement.append_attribute("version") = "6.01"; gbXMLElement.append_attribute("SurfaceReferenceLocation") = "Centerline"; - boost::optional facility = model.getOptionalUniqueModelObject(); - if (facility) { - translateFacility(*facility, gbXMLElement); - } + // translateFacility is responsible to translate Surfaces, and calls translateBuilding, which is responsible to translate spaces + // so we do need to call it anyways. + translateFacility(model, gbXMLElement); // do constructions std::vector constructionBases = model.getModelObjects(); @@ -412,35 +411,36 @@ namespace gbxml { return true; } - boost::optional ForwardTranslator::translateFacility(const openstudio::model::Facility& facility, pugi::xml_node& parent) + boost::optional ForwardTranslator::translateFacility(const openstudio::model::Model& model, pugi::xml_node& parent) { + + // `model` is `const`, so we shouldn't call getUniqueModelObject which will **create** a new object in there. + boost::optional _facility = model.getOptionalUniqueModelObject(); + auto result = parent.append_child("Campus"); - m_translatedObjects[facility.handle()] = result; + std::string name = "Facility"; - boost::optional name = facility.name(); + if (_facility) { + m_translatedObjects[_facility->handle()] = result; + if (auto _s = _facility->name()) { + name = _s.get(); + } + } // id result.append_attribute("id") = "Facility"; // name auto nameElement = result.append_child("Name"); - if (name) { - nameElement.text() = name.get().c_str(); - } else { - nameElement.text() = "Facility"; - } - - model::Model model = facility.model(); + nameElement.text() = name.c_str(); // todo: translate location - // translate building - boost::optional building = model.getOptionalUniqueModelObject(); - if (building) { - translateBuilding(*building, result); - } + // translate building: needs to be done even if not explicitly instantiated since that's what translates Spaces in particular. + translateBuilding(model, result); // translate surfaces + // TODO: JM 2020-06-18 Why is translateSpace not responsible to call this one? std::vector surfaces = model.getConcreteModelObjects(); if (m_progressBar) { m_progressBar->setWindowTitle(toString("Translating Surfaces")); @@ -477,36 +477,46 @@ namespace gbxml { return result; } - boost::optional ForwardTranslator::translateBuilding(const openstudio::model::Building& building, pugi::xml_node& parent) + boost::optional ForwardTranslator::translateBuilding(const openstudio::model::Model& model, pugi::xml_node& parent) { + // `model` is `const`, so we shouldn't call getUniqueModelObject which will **create** a new object in there. + // model::Building building = model.getUniqueModelObject(); + boost::optional _building = model.getOptionalUniqueModelObject(); + auto result = parent.append_child("Building"); - m_translatedObjects[building.handle()] = result; + std::string bName = "Building"; + std::string bType = "Unknown"; + if (_building) { + m_translatedObjects[_building->handle()] = result; + bName = _building->nameString(); + + if (boost::optional _standardsBuildingType = _building->standardsBuildingType()) { + // TODO: map to gbXML types + // bType = escapeName(_standardsBuildingType.get()).c_str(); + } + + // space type + if (boost::optional _spaceType = _building->spaceType()) { + //std::string spaceTypeName = _spaceType->nameString(); + // TODO: map to gbXML types + // bType = escapeName(spaceTypeName).c_str(); + } + + } // id - std::string name = building.name().get(); - result.append_attribute("id") = escapeName(name).c_str(); + result.append_attribute("id") = escapeName(bName).c_str(); // building type - //result.append_attribute("buildingType") = "Office"; - result.append_attribute("buildingType") = "Unknown"; + result.append_attribute("buildingType") = bType.c_str(); - boost::optional standardsBuildingType = building.standardsBuildingType(); - if (standardsBuildingType) { - // todo: map to gbXML types - //result.append_attribute("buildingType") = escapeName(spaceTypeName).c_str(); - } + if (_building) { - // space type - boost::optional spaceType = building.spaceType(); - if (spaceType) { - //std::string spaceTypeName = spaceType->name().get(); - // todo: map to gbXML types - //result.append_attribute("buildingType", escapeName(spaceTypeName)); } // name auto nameElement = result.append_child("Name"); - nameElement.text() = name.c_str(); + nameElement.text() = bName.c_str(); // area auto areaElement = result.append_child("Area"); @@ -514,7 +524,7 @@ namespace gbxml { // DLM: we want to use gbXML's definition of floor area which includes area from all spaces with people in them //double floorArea = building.floorArea(); - std::vector spaces = building.spaces(); + std::vector spaces = model.getConcreteModelObjects(); double floorArea = 0; for (const model::Space& space : spaces) { @@ -543,7 +553,7 @@ namespace gbxml { } // translate shading surface groups - model::ShadingSurfaceGroupVector shadingSurfaceGroups = building.model().getConcreteModelObjects(); + model::ShadingSurfaceGroupVector shadingSurfaceGroups = model.getConcreteModelObjects(); if (m_progressBar) { m_progressBar->setWindowTitle(toString("Translating Shading Surface Groups")); m_progressBar->setMinimum(0); @@ -560,7 +570,7 @@ namespace gbxml { } // translate stories - model::BuildingStoryVector stories = building.model().getConcreteModelObjects(); + model::BuildingStoryVector stories = model.getConcreteModelObjects(); if (m_progressBar) { m_progressBar->setWindowTitle(toString("Translating Stories")); m_progressBar->setMinimum(0); diff --git a/src/gbxml/ForwardTranslator.hpp b/src/gbxml/ForwardTranslator.hpp index 58de994c9a9..19a57999425 100644 --- a/src/gbxml/ForwardTranslator.hpp +++ b/src/gbxml/ForwardTranslator.hpp @@ -92,8 +92,12 @@ namespace gbxml { // listed in translation order bool translateModel(const openstudio::model::Model& model, pugi::xml_document& document); - boost::optional translateFacility(const openstudio::model::Facility& facility, pugi::xml_node& parent); - boost::optional translateBuilding(const openstudio::model::Building& building, pugi::xml_node& parent); + + // Facility and Building could not be explicitly instantiated in the model, but the functions still need to be called so that Spaces and surfaces + // are translated. Facility and Building both are UniqueModelObjects, so passing model here as an argument is harmless + boost::optional translateFacility(const openstudio::model::Model& model, pugi::xml_node& parent); + boost::optional translateBuilding(const openstudio::model::Model& model, pugi::xml_node& parent); + boost::optional translateSpace(const openstudio::model::Space& space, pugi::xml_node& parent); boost::optional translateShadingSurfaceGroup(const openstudio::model::ShadingSurfaceGroup& shadingSurfaceGroup, pugi::xml_node& parent); boost::optional translateBuildingStory(const openstudio::model::BuildingStory& story, pugi::xml_node& parent);