From cc407266185d1dc89912a662853e5565ba512b47 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 23 Jul 2020 11:27:38 +0200 Subject: [PATCH] Fix SVG storey sorting and element naming --- src/serializers/SvgSerializer.cpp | 38 +++++++++++++++++++++---------- src/serializers/SvgSerializer.h | 23 +++++++++++++++---- 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/serializers/SvgSerializer.cpp b/src/serializers/SvgSerializer.cpp index d7fbc241d2..54ea948171 100644 --- a/src/serializers/SvgSerializer.cpp +++ b/src/serializers/SvgSerializer.cpp @@ -465,7 +465,7 @@ void SvgSerializer::write(const IfcGeom::BRepElement* o) // No intersection with bounding box, fail early if (zmin > cut_z || zmax < cut_z) continue; - po = &start_path(storey, nameElement(o)); + po = &start_path(storey, nameElement(storey, o)); // Create a horizontal cross section 1 meter above the bottom point of the shape const gp_Pln pln(gp_Pnt(0, 0, cut_z), gp::DZ()); @@ -686,28 +686,41 @@ namespace { } } -std::string SvgSerializer::nameElement(const IfcGeom::Element* elem) { - return nameElement_({ {"id", object_id(elem)}, {"class", elem->type()}, {"data-name", elem->name()} }); +std::string SvgSerializer::nameElement(const IfcUtil::IfcBaseEntity* storey, const IfcGeom::Element* elem) { + return nameElement_({ + {"id", with_section_heights_from_storey_ ? object_id(storey, elem) : GeometrySerializer::object_id(elem)}, + {"class", elem->type()}, + {"data-name", elem->name()}, + {"data-guid", elem->guid()} + }); +} + +std::string SvgSerializer::idElement(const IfcUtil::IfcBaseEntity* elem) { + const std::string type = elem->declaration().is("IfcBuildingStorey") ? "storey" : "product"; + const std::string name = + (settings().get(SerializerSettings::USE_ELEMENT_GUIDS) + ? static_cast(*elem->get("GlobalId")) + : ((settings().get(SerializerSettings::USE_ELEMENT_NAMES) && !elem->get("Name")->isNull())) + ? static_cast(*elem->get("Name")) + : IfcParse::IfcGlobalId(*elem->get("GlobalId")).formatted()); + return type + "-" + name; } std::string SvgSerializer::nameElement(const IfcUtil::IfcBaseEntity* elem) { if (elem == 0) { return ""; } const std::string& entity = elem->declaration().name(); - const std::string type = elem->declaration().is("IfcBuildingStorey") ? "storey" : "product"; std::string ifc_name; if (!elem->get("Name")->isNull()) { ifc_name = (std::string) *elem->get("Name"); } - const std::string name = - (settings().get(SerializerSettings::USE_ELEMENT_GUIDS) - ? static_cast(*elem->get("GlobalId")) - : ((settings().get(SerializerSettings::USE_ELEMENT_NAMES) && !elem->get("Name")->isNull())) - ? static_cast(*elem->get("Name")) - : IfcParse::IfcGlobalId(*elem->get("GlobalId")).formatted()); - - return nameElement_({ {"id", type + "-" + name}, {"class", entity}, {"data-name", ifc_name} }); + return nameElement_({ + {"id", idElement(elem)}, + {"class", entity}, + {"data-name", ifc_name}, + {"data-guid", *elem->get("GlobalId")} + }); } void SvgSerializer::setFile(IfcParse::IfcFile* f) { @@ -748,6 +761,7 @@ void SvgSerializer::setSectionHeight(double h, IfcUtil::IfcBaseEntity* storey) { } void SvgSerializer::setSectionHeightsFromStoreys(double offset) { + with_section_heights_from_storey_ = true; section_heights.emplace(); auto storeys = file->instances_by_type("IfcBuildingStorey"); const double lu = file->getUnit("LENGTHUNIT").second; diff --git a/src/serializers/SvgSerializer.h b/src/serializers/SvgSerializer.h index b4deecb61c..2e23ac624a 100644 --- a/src/serializers/SvgSerializer.h +++ b/src/serializers/SvgSerializer.h @@ -42,7 +42,11 @@ struct storey_sorter { b_elev = static_cast(*b->get("Elevation")); } catch (...) {}; if (a_elev && b_elev) { - return std::less()(*a_elev, *b_elev); + if (std::equal_to()(*a_elev, *b_elev)) { + return std::less()(a->data().id(), b->data().id()); + } else { + return std::less()(*a_elev, *b_elev); + } } boost::optional a_name, b_name; @@ -51,7 +55,11 @@ struct storey_sorter { b_name = static_cast(*b->get("Name")); } catch (...) {}; if (a_name && b_name) { - return std::less()(*a_name, *b_name); + if (std::equal_to()(*a_name, *b_name)) { + return std::less()(a->data().id(), b->data().id()); + } else { + return std::less()(*a_name, *b_name); + } } } return std::less()(a, b); @@ -65,7 +73,7 @@ protected: std::ofstream svg_file; double xmin, ymin, xmax, ymax, width, height; boost::optional>> section_heights; - bool rescale, print_space_names_, print_space_areas_, draw_door_arcs_; + bool rescale, print_space_names_, print_space_areas_, draw_door_arcs_, with_section_heights_from_storey_; std::multimap paths; std::vector< boost::shared_ptr > xcoords; std::vector< boost::shared_ptr > ycoords; @@ -80,6 +88,7 @@ public: , ymin(+std::numeric_limits::infinity()) , xmax(-std::numeric_limits::infinity()) , ymax(-std::numeric_limits::infinity()) + , with_section_heights_from_storey_(false) , rescale(false) , file(0) , storey_(0) @@ -104,8 +113,12 @@ public: void setPrintSpaceNames(bool b) { print_space_names_ = b; } void setPrintSpaceAreas(bool b) { print_space_areas_ = b; } void setDrawDoorArcs(bool b) { draw_door_arcs_ = b; } - std::string nameElement(const IfcGeom::Element* elem); - std::string nameElement(const IfcUtil::IfcBaseEntity* elem); + std::string nameElement(const IfcUtil::IfcBaseEntity* storey, const IfcGeom::Element* elem); + std::string nameElement(const IfcUtil::IfcBaseEntity* elem); + std::string idElement(const IfcUtil::IfcBaseEntity* elem); + std::string object_id(const IfcUtil::IfcBaseEntity* storey, const IfcGeom::Element* o) { + return idElement(storey) + "-" + GeometrySerializer::object_id(o); + } }; #endif