mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-13 19:07:57 +00:00
ifcgeom: resolve default materials through the schema supertype chain (#473)
get_default_style did an exact-name map lookup, so subtypes like IfcWallStandardCase or IfcSlabStandardCase never inherited the default material of their parent type, falling through to the generic grey DefaultMaterial instead. This was reported in 2018 (#473) and the fix direction (walk up the supertype chain once the schema runtime made supertypes available) was agreed there, but never implemented. On an exact-match miss the lookup now walks decl->supertype() until a mapped ancestor is found, caching the result under the leaf name for O(1) subsequent lookups. The product's user-facing type string is deliberately untouched; only the style lookup gained inheritance. Applies equally to the built-in defaults and --default-material-file. This change was written with AI assistance.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include "../ifcgeom/IfcGeomRenderStyles.h"
|
||||
#include "../ifcparse/IfcSchema.h"
|
||||
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
@@ -112,15 +113,35 @@ void IfcGeom::set_default_style_file(const std::string& json_file) {
|
||||
}
|
||||
}
|
||||
|
||||
const ifcopenshell::geometry::taxonomy::style::ptr& IfcGeom::get_default_style(const std::string& s) {
|
||||
const ifcopenshell::geometry::taxonomy::style::ptr& IfcGeom::get_default_style(const std::string& s, const IfcParse::declaration* decl) {
|
||||
static std::mutex m;
|
||||
std::lock_guard<std::mutex> lk(m);
|
||||
|
||||
if (!default_materials_initialized) InitDefaultMaterials();
|
||||
auto it = default_materials.find(s);
|
||||
if (it == default_materials.end() && decl != nullptr) {
|
||||
// No style registered for this exact type. Walk up the schema's supertype
|
||||
// chain (e.g. IfcSlabStandardCase -> IfcSlab) so a style registered for a
|
||||
// supertype is inherited by its subtypes, rather than always falling back
|
||||
// to the generic default style.
|
||||
const IfcParse::entity* entity = decl->as_entity();
|
||||
const IfcParse::entity* super = entity ? entity->supertype() : nullptr;
|
||||
while (super != nullptr) {
|
||||
auto super_it = default_materials.find(super->name());
|
||||
if (super_it != default_materials.end()) {
|
||||
it = super_it;
|
||||
break;
|
||||
}
|
||||
super = super->supertype();
|
||||
}
|
||||
}
|
||||
if (it == default_materials.end()) {
|
||||
default_materials.insert(std::make_pair(s, default_material));
|
||||
it = default_materials.find(s);
|
||||
} else if (it->first != s) {
|
||||
// Cache the resolved (inherited) style under the leaf type name too, so
|
||||
// repeated lookups for this exact type are O(1) afterwards.
|
||||
default_materials.insert(std::make_pair(s, it->second));
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user