From cdd1ecd15cdcfc81ac1f8b6411de7cdf3fd497f0 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Fri, 3 Jul 2026 13:28:02 +0200 Subject: [PATCH] Update parse examples --- src/examples/IfcParseExamples.cpp | 188 ++++-------------------------- 1 file changed, 21 insertions(+), 167 deletions(-) diff --git a/src/examples/IfcParseExamples.cpp b/src/examples/IfcParseExamples.cpp index c81c37cfdd..448dcb0198 100644 --- a/src/examples/IfcParseExamples.cpp +++ b/src/examples/IfcParseExamples.cpp @@ -20,166 +20,21 @@ // TODO: Multiple schemas #define IfcSchema Ifc2x3 +#include "../helpers/pset.h" #include "../ifcparse/file.h" #include "../ifcparse/logger.h" #include "../ifcparse/schemas/Ifc2x3.h" -#ifdef _MSC_VER -#define strcasecmp _stricmp -#endif - -#include - #if USE_VLD #include #endif -template -struct is_ifc4_or_higher : std::false_type {}; - -template -struct is_ifc4_or_higher> : std::true_type { }; - -typedef std::map> element_properties; - -std::string format_string(const attribute_value& argument) { - // Argument is a runtime tagged variant for the various data types in a IFC model, - // in this particular case we only care about flattening it to a string. - // @todo mostly duplicated from XmlSerializer.cpp - if (argument.isNull()) { - return "-"; - } - auto argument_type = argument.type(); - switch (argument_type) { - case ifcopenshell::Argument_BOOL: { - const bool b = argument; - return b ? "true" : "false"; - } - case ifcopenshell::Argument_DOUBLE: { - const double d = argument; - std::stringstream stream; - stream << std::setprecision(std::numeric_limits< double >::max_digits10) << d; - return stream.str(); - break; } - case ifcopenshell::Argument_STRING: - case ifcopenshell::Argument_ENUMERATION: { - return static_cast(argument); - break; } - case ifcopenshell::Argument_INT: { - const int v = argument; - std::stringstream stream; - stream << v; - return stream.str(); - break; } - } - return "?"; -} - -template -void process_pset(element_properties& props, const T& inst) { - // Process an individual Property or Quantity set. - if (auto pset = inst.template as()) { - if (!pset.Name()) { - return; - } - auto ps = pset.HasProperties(); - for (auto& p : ps) { - if (auto singleval = p.template as()) { - std::string propname, propvalue; - if constexpr (is_ifc4_or_higher::value) { - if (!singleval.Name()) { - continue; - } - propname = *singleval.Name(); - } - if constexpr (!is_ifc4_or_higher::value) { - propname = singleval.Name(); - } - if (!singleval.NominalValue()) { - propvalue = "-"; - } else { - props[*pset.Name()][propname] = format_string(singleval.NominalValue().concrete().get_attribute_value(0)); - } - } - } - } - if (auto qset = inst.template as()) { - if (!qset.Name()) { - return; - } - auto qs = qset.Quantities(); - for (auto& q : qs) { - if (q.template as() && q.get_attribute_value(3).type() == ifcopenshell::Argument_DOUBLE) { - double v = q.get_attribute_value(3); - props[*qset.Name()][q.Name()] = std::to_string(v); - } - } - } - if constexpr (is_ifc4_or_higher::value) { - if (auto extprops = inst->template as()) { - // @todo - } - } -} - -template -void get_psets_s(element_properties& props, const typename Schema::IfcObjectDefinition& inst) { - // Extracts the property definitions for an IFC instance. - if (auto tyob = inst.template as()) { - if (tyob.HasPropertySets()) { - auto defs = *tyob.HasPropertySets(); - for (auto& def : defs) { - process_pset(props, def); - } - } - } - if constexpr (is_ifc4_or_higher::value) { - if (auto mdef = inst.template as()) { - auto defs = mdef.HasProperties(); - for (auto& def : defs) { - process_pset(props, def); - } - } - if (auto pdef = inst.template as()) { - auto defs = pdef->HasProperties(); - for (auto& def : defs) { - process_pset(props, def); - } - } - } - if (auto ob = inst.template as()) { - if constexpr (is_ifc4_or_higher::value) { - auto rels = ob.IsTypedBy(); - for (auto& rel : rels) { - get_psets_s(props, rel->RelatingType()); - } - } - { - auto rels = ob.IsDefinedBy(); - for (auto& rel : rels) { - if (auto bytype = rel.template as()) { - get_psets_s(props, bytype.RelatingType()); - } else if (auto byprops = rel.template as()) { - process_pset(props, byprops.RelatingPropertyDefinition()); - } - } - } - } -} - -void get_psets(element_properties& props, const express::Base& inst) { - auto schema_name = inst.declaration().schema()->name().c_str(); - if (strcasecmp(schema_name, "Ifc2x3") == 0) { - get_psets_s(props, inst.as()); - } -} - int main(int argc, char** argv) { - if (argc != 2) { + if (argc != 2) { std::cout << "usage: IfcParseExamples " << std::endl; return 1; } - + // Redirect the output (both progress and log) to stdout logger::set_output(&std::cout, &std::cout); @@ -206,13 +61,13 @@ int main(int argc, char** argv) { // we need to cast them to IfcWindows. Since these properties // are optional we need to make sure the properties are // defined for the window in question before accessing them. - auto elements = file.instances_by_type(); + auto elements = file.instances_by_type(); std::cout << "Found " << elements.size() << " elements in " << argv[1] << ":" << std::endl; for (auto& element : elements) { - element.to_string(std::cout); - std::cout << std::endl; + element.to_string(std::cout); + std::cout << std::endl; if (auto window = element.as()) { if (window.OverallWidth() && window.OverallHeight()) { @@ -221,22 +76,21 @@ int main(int argc, char** argv) { } } - element_properties props; - get_psets(props, element); + element_properties props = get_psets(element); - for (auto& ps : props) { - std::cout << ps.first << std::endl; - std::cout << std::string(ps.first.size(), '=') << std::endl; - size_t max_key_len = 0; - for (auto& p : ps.second) { - if (p.first.size() > max_key_len) { - max_key_len = p.first.size(); - } - } - for (auto& p : ps.second) { - std::cout << p.first << std::string(max_key_len - p.first.size(), ' ') << ":" << p.second << std::endl; - } - std::cout << std::endl; - } + for (auto& ps : props) { + std::cout << ps.first << std::endl; + std::cout << std::string(ps.first.size(), '=') << std::endl; + size_t max_key_len = 0; + for (auto& p : ps.second) { + if (p.first.size() > max_key_len) { + max_key_len = p.first.size(); + } + } + for (auto& p : ps.second) { + std::cout << p.first << std::string(max_key_len - p.first.size(), ' ') << ":" << p.second << std::endl; + } + std::cout << std::endl; + } } }