From f67449384378f035478eebdfa3366716b6c3aad2 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Fri, 4 Jul 2014 16:37:21 +0200 Subject: [PATCH] Fixed retrieving attributes derived in subtype Convert argument type enumeration to python string Add ability to iterate over all instances from python --- src/ifcexpressparser/templates.py | 27 +++++++++++++++++++++++---- src/ifcparse/Ifc2x3-rt.cpp | 26 ++++++++++++++++++++++---- src/ifcparse/Ifc2x3-rt.h | 1 + src/ifcparse/Ifc4-rt.cpp | 28 +++++++++++++++++++++++----- src/ifcparse/Ifc4-rt.h | 1 + src/ifcparse/IfcUntypedEntity.cpp | 4 +++- src/ifcparse/IfcUtil.h | 2 +- src/ifcwrap/IfcPython.i | 7 ++++++- src/ifcwrap/Interface.h | 9 +++++++++ src/ifcwrap/ifc.py | 9 ++++++++- 10 files changed, 97 insertions(+), 17 deletions(-) diff --git a/src/ifcexpressparser/templates.py b/src/ifcexpressparser/templates.py index 6f139c66fb..a5fc3a0cc8 100644 --- a/src/ifcexpressparser/templates.py +++ b/src/ifcexpressparser/templates.py @@ -88,6 +88,7 @@ namespace Type { IfcUtil::ArgumentType GetAttributeType(Enum t, unsigned char a); const std::string& GetAttributeName(Enum t, unsigned char a); bool GetAttributeOptional(Enum t, unsigned char a); + bool GetAttributeDerived(Enum t, unsigned char a); std::pair GetEnumerationIndex(Enum t, const std::string& a); std::pair GetInverseAttribute(Enum t, const std::string& a); Enum GetAttributeEnumerationClass(Enum t, unsigned char a); @@ -167,6 +168,8 @@ bool Type::IsSimple(Enum v) { """ rt_implementation = """ +#include + #include "../ifcparse/%(schema_name)s.h" #include "../ifcparse/%(schema_name)s-rt.h" #include "../ifcparse/IfcException.h" @@ -183,6 +186,8 @@ using namespace IfcUtil; std::map entity_descriptor_map; std::map enumeration_descriptor_map; std::map, std::pair > inverse_map; +std::map > derived_map; + void InitDescriptorMap() { IfcEntityDescriptor* current; %(entity_descriptors)s @@ -196,6 +201,10 @@ void InitInverseMap() { %(inverse_implementations)s } +void InitDerivedMap() { +%(derived_field_statements)s +} + int Type::GetAttributeIndex(Enum t, const std::string& a) { if (entity_descriptor_map.empty()) ::InitDescriptorMap(); std::map::const_iterator i = entity_descriptor_map.find(t); @@ -231,6 +240,12 @@ bool Type::GetAttributeOptional(Enum t, unsigned char a) { else return i->second->getArgumentOptional(a); } +bool Type::GetAttributeDerived(Enum t, unsigned char a) { + if (derived_map.empty()) ::InitDerivedMap(); + std::map >::const_iterator i = derived_map.find(t); + return i != derived_map.end() && i->second.find(a) != i->second.end(); +} + std::pair Type::GetEnumerationIndex(Enum t, const std::string& a) { if (enumeration_descriptor_map.empty()) ::InitDescriptorMap(); std::map::const_iterator i = enumeration_descriptor_map.find(t); @@ -262,8 +277,12 @@ Type::Enum Type::GetAttributeEnumerationClass(Enum t, unsigned char a) { } void Type::PopulateDerivedFields(IfcWrite::IfcWritableEntity* e) { - Type::Enum type = e->type(); -%(derived_field_statements)s + std::map >::const_iterator i = derived_map.find(e->type()); + if (i != derived_map.end()) { + for (std::set::const_iterator it = i->second.begin(); it != i->second.end(); ++it) { + e->setArgumentDerived(*it); + } + } } """ @@ -280,8 +299,8 @@ enumeration_descriptor = """ values.clear(); values.reserve(128); enumeration_descriptor_value = ' values.push_back("%(name)s");' -derived_field_statement = ' if (type == Type::%(type)s) { %(statements)s}'; -derived_field_statement_attrs = 'e->setArgumentDerived(%d); ' +derived_field_statement = ' {std::set idxs; %(statements)sderived_map[Type::%(type)s] = idxs;}'; +derived_field_statement_attrs = 'idxs.insert(%d); ' simpletype = """%(documentation)s typedef %(type)s %(name)s; diff --git a/src/ifcparse/Ifc2x3-rt.cpp b/src/ifcparse/Ifc2x3-rt.cpp index 92c15a12aa..7ba9e60e52 100644 --- a/src/ifcparse/Ifc2x3-rt.cpp +++ b/src/ifcparse/Ifc2x3-rt.cpp @@ -26,6 +26,8 @@ #ifndef USE_IFC4 +#include + #include "../ifcparse/Ifc2x3.h" #include "../ifcparse/Ifc2x3-rt.h" #include "../ifcparse/IfcException.h" @@ -42,6 +44,8 @@ using namespace IfcUtil; std::map entity_descriptor_map; std::map enumeration_descriptor_map; std::map, std::pair > inverse_map; +std::map > derived_map; + void InitDescriptorMap() { IfcEntityDescriptor* current; current = entity_descriptor_map[Type::IfcAbsorbedDoseMeasure] = new IfcEntityDescriptor(Type::IfcAbsorbedDoseMeasure,0); @@ -4166,6 +4170,12 @@ void InitInverseMap() { inverse_map.insert(std::make_pair(std::make_pair(Type::IfcTypeObject, "ObjectTypeOf"), std::make_pair(Type::IfcRelDefinesByType, 5))); } +void InitDerivedMap() { + {std::set idxs; idxs.insert(2); idxs.insert(3); idxs.insert(4); idxs.insert(5); derived_map[Type::IfcGeometricRepresentationSubContext] = idxs;} + {std::set idxs; idxs.insert(0); idxs.insert(1); derived_map[Type::IfcOrientedEdge] = idxs;} + {std::set idxs; idxs.insert(0); derived_map[Type::IfcSIUnit] = idxs;} +} + int Type::GetAttributeIndex(Enum t, const std::string& a) { if (entity_descriptor_map.empty()) ::InitDescriptorMap(); std::map::const_iterator i = entity_descriptor_map.find(t); @@ -4201,6 +4211,12 @@ bool Type::GetAttributeOptional(Enum t, unsigned char a) { else return i->second->getArgumentOptional(a); } +bool Type::GetAttributeDerived(Enum t, unsigned char a) { + if (derived_map.empty()) ::InitDerivedMap(); + std::map >::const_iterator i = derived_map.find(t); + return i != derived_map.end() && i->second.find(a) != i->second.end(); +} + std::pair Type::GetEnumerationIndex(Enum t, const std::string& a) { if (enumeration_descriptor_map.empty()) ::InitDescriptorMap(); std::map::const_iterator i = enumeration_descriptor_map.find(t); @@ -4232,9 +4248,11 @@ Type::Enum Type::GetAttributeEnumerationClass(Enum t, unsigned char a) { } void Type::PopulateDerivedFields(IfcWrite::IfcWritableEntity* e) { - Type::Enum type = e->type(); - if (type == Type::IfcGeometricRepresentationSubContext) { e->setArgumentDerived(2); e->setArgumentDerived(3); e->setArgumentDerived(4); e->setArgumentDerived(5); } - if (type == Type::IfcOrientedEdge) { e->setArgumentDerived(0); e->setArgumentDerived(1); } - if (type == Type::IfcSIUnit) { e->setArgumentDerived(0); } + std::map >::const_iterator i = derived_map.find(e->type()); + if (i != derived_map.end()) { + for (std::set::const_iterator it = i->second.begin(); it != i->second.end(); ++it) { + e->setArgumentDerived(*it); + } + } } #endif diff --git a/src/ifcparse/Ifc2x3-rt.h b/src/ifcparse/Ifc2x3-rt.h index bd180a8579..5cb8964e91 100644 --- a/src/ifcparse/Ifc2x3-rt.h +++ b/src/ifcparse/Ifc2x3-rt.h @@ -40,6 +40,7 @@ namespace Type { IfcUtil::ArgumentType GetAttributeType(Enum t, unsigned char a); const std::string& GetAttributeName(Enum t, unsigned char a); bool GetAttributeOptional(Enum t, unsigned char a); + bool GetAttributeDerived(Enum t, unsigned char a); std::pair GetEnumerationIndex(Enum t, const std::string& a); std::pair GetInverseAttribute(Enum t, const std::string& a); Enum GetAttributeEnumerationClass(Enum t, unsigned char a); diff --git a/src/ifcparse/Ifc4-rt.cpp b/src/ifcparse/Ifc4-rt.cpp index 5e726b1c30..3243c95ab7 100644 --- a/src/ifcparse/Ifc4-rt.cpp +++ b/src/ifcparse/Ifc4-rt.cpp @@ -26,6 +26,8 @@ #ifdef USE_IFC4 +#include + #include "../ifcparse/Ifc4.h" #include "../ifcparse/Ifc4-rt.h" #include "../ifcparse/IfcException.h" @@ -42,6 +44,8 @@ using namespace IfcUtil; std::map entity_descriptor_map; std::map enumeration_descriptor_map; std::map, std::pair > inverse_map; +std::map > derived_map; + void InitDescriptorMap() { IfcEntityDescriptor* current; current = entity_descriptor_map[Type::IfcAbsorbedDoseMeasure] = new IfcEntityDescriptor(Type::IfcAbsorbedDoseMeasure,0); @@ -4854,6 +4858,13 @@ void InitInverseMap() { inverse_map.insert(std::make_pair(std::make_pair(Type::IfcTypeResource, "ResourceOf"), std::make_pair(Type::IfcRelAssignsToResource, 6))); } +void InitDerivedMap() { + {std::set idxs; idxs.insert(2); idxs.insert(3); idxs.insert(4); idxs.insert(5); derived_map[Type::IfcGeometricRepresentationSubContext] = idxs;} + {std::set idxs; idxs.insert(3); derived_map[Type::IfcMirroredProfileDef] = idxs;} + {std::set idxs; idxs.insert(0); idxs.insert(1); derived_map[Type::IfcOrientedEdge] = idxs;} + {std::set idxs; idxs.insert(0); derived_map[Type::IfcSIUnit] = idxs;} +} + int Type::GetAttributeIndex(Enum t, const std::string& a) { if (entity_descriptor_map.empty()) ::InitDescriptorMap(); std::map::const_iterator i = entity_descriptor_map.find(t); @@ -4889,6 +4900,12 @@ bool Type::GetAttributeOptional(Enum t, unsigned char a) { else return i->second->getArgumentOptional(a); } +bool Type::GetAttributeDerived(Enum t, unsigned char a) { + if (derived_map.empty()) ::InitDerivedMap(); + std::map >::const_iterator i = derived_map.find(t); + return i != derived_map.end() && i->second.find(a) != i->second.end(); +} + std::pair Type::GetEnumerationIndex(Enum t, const std::string& a) { if (enumeration_descriptor_map.empty()) ::InitDescriptorMap(); std::map::const_iterator i = enumeration_descriptor_map.find(t); @@ -4920,10 +4937,11 @@ Type::Enum Type::GetAttributeEnumerationClass(Enum t, unsigned char a) { } void Type::PopulateDerivedFields(IfcWrite::IfcWritableEntity* e) { - Type::Enum type = e->type(); - if (type == Type::IfcGeometricRepresentationSubContext) { e->setArgumentDerived(2); e->setArgumentDerived(3); e->setArgumentDerived(4); e->setArgumentDerived(5); } - if (type == Type::IfcMirroredProfileDef) { e->setArgumentDerived(3); } - if (type == Type::IfcOrientedEdge) { e->setArgumentDerived(0); e->setArgumentDerived(1); } - if (type == Type::IfcSIUnit) { e->setArgumentDerived(0); } + std::map >::const_iterator i = derived_map.find(e->type()); + if (i != derived_map.end()) { + for (std::set::const_iterator it = i->second.begin(); it != i->second.end(); ++it) { + e->setArgumentDerived(*it); + } + } } #endif diff --git a/src/ifcparse/Ifc4-rt.h b/src/ifcparse/Ifc4-rt.h index d5233f0106..77f5b7bb94 100644 --- a/src/ifcparse/Ifc4-rt.h +++ b/src/ifcparse/Ifc4-rt.h @@ -40,6 +40,7 @@ namespace Type { IfcUtil::ArgumentType GetAttributeType(Enum t, unsigned char a); const std::string& GetAttributeName(Enum t, unsigned char a); bool GetAttributeOptional(Enum t, unsigned char a); + bool GetAttributeDerived(Enum t, unsigned char a); std::pair GetEnumerationIndex(Enum t, const std::string& a); std::pair GetInverseAttribute(Enum t, const std::string& a); Enum GetAttributeEnumerationClass(Enum t, unsigned char a); diff --git a/src/ifcparse/IfcUntypedEntity.cpp b/src/ifcparse/IfcUntypedEntity.cpp index edb0c86c62..0ac2416abe 100644 --- a/src/ifcparse/IfcUntypedEntity.cpp +++ b/src/ifcparse/IfcUntypedEntity.cpp @@ -54,7 +54,9 @@ unsigned int IfcParse::IfcUntypedEntity::getArgumentCount() const { return IfcSchema::Type::GetAttributeCount(_type); } IfcUtil::ArgumentType IfcParse::IfcUntypedEntity::getArgumentType(unsigned int i) const { - return IfcSchema::Type::GetAttributeType(_type,i); + return IfcSchema::Type::GetAttributeDerived(_type, i) + ? IfcUtil::Argument_DERIVED + : IfcSchema::Type::GetAttributeType(_type,i); } ArgumentPtr IfcParse::IfcUntypedEntity::getArgument(unsigned int i) const { return entity->getArgument(i); diff --git a/src/ifcparse/IfcUtil.h b/src/ifcparse/IfcUtil.h index 1655277cfc..b1deffaaf3 100644 --- a/src/ifcparse/IfcUtil.h +++ b/src/ifcparse/IfcUtil.h @@ -53,7 +53,7 @@ inline T* reinterpret_pointer_cast(F* from) { namespace IfcUtil { enum ArgumentType { - Argument_INT, Argument_BOOL, Argument_DOUBLE, Argument_STRING, Argument_VECTOR_INT, Argument_VECTOR_DOUBLE, Argument_VECTOR_STRING, Argument_ENTITY, Argument_ENTITY_LIST, Argument_ENTITY_LIST_LIST, Argument_ENUMERATION, Argument_UNKNOWN + Argument_INT, Argument_BOOL, Argument_DOUBLE, Argument_STRING, Argument_VECTOR_INT, Argument_VECTOR_DOUBLE, Argument_VECTOR_STRING, Argument_ENTITY, Argument_ENTITY_LIST, Argument_ENTITY_LIST_LIST, Argument_ENUMERATION, Argument_DERIVED, Argument_UNKNOWN }; } diff --git a/src/ifcwrap/IfcPython.i b/src/ifcwrap/IfcPython.i index 6989be8d87..3c844693e4 100644 --- a/src/ifcwrap/IfcPython.i +++ b/src/ifcwrap/IfcPython.i @@ -76,10 +76,15 @@ } } +%typemap(out) IfcUtil::ArgumentType { + const char* strs[] = {"INT", "BOOL", "DOUBLE", "STRING", "VECTOR_INT", "VECTOR_DOUBLE", "VECTOR_STRING", "ENTITY", "ENTITY_LIST", "ENTITY_LIST_LIST", "ENUMERATION", "DERIVED", "UNKNOWN"}; + $result = SWIG_Python_str_FromChar(strs[$1]); +} + %typemap(out) std::pair { const Argument& arg = *($1.second); const IfcUtil::ArgumentType type = $1.first; - if (arg.isNull()) { + if (arg.isNull() || type == IfcUtil::Argument_DERIVED) { Py_INCREF(Py_None); $result = Py_None; } else { diff --git a/src/ifcwrap/Interface.h b/src/ifcwrap/Interface.h index a8aea7ee54..5c41f0489f 100644 --- a/src/ifcwrap/Interface.h +++ b/src/ifcwrap/Interface.h @@ -85,6 +85,15 @@ namespace IfcParse { void AddEntity(IfcUtil::IfcSchemaEntity e); IfcFile(); ~IfcFile(); + + std::vector entity_names() const { + std::vector keys; + keys.reserve(byid.size()); + for (MapEntityById::const_iterator it = byid.begin(); it != byid.end(); ++ it) { + keys.push_back(it->first); + } + return keys; + } }; IfcParse::IfcFile* open(const std::string& s) { diff --git a/src/ifcwrap/ifc.py b/src/ifcwrap/ifc.py index 7735f180b8..6849192942 100644 --- a/src/ifcwrap/ifc.py +++ b/src/ifcwrap/ifc.py @@ -30,10 +30,15 @@ class entity_instance: classes = list(map(type, v)) if ifc_wrapper.entity_instance in classes: return list(map(wrap, v)) return v + def attribute_type(self, attr): + attr_idx = attr if isinstance(attr, int) else self.wrapped_data.get_argument_index(attr) + return self.wrapped_data.get_argument_type(attr_idx) + def attribute_name(self, attr_idx): + return self.wrapped_data.get_argument_name(attr_idx) def __setattr__(self, key, value): self[self.wrapped_data.get_argument_index(key)] = value def __getitem__(self, key): - return entity_instance.wrap_value(self.wrapped_data.get_argument(self.wrapped_data.get_argument_index(name))) + return entity_instance.wrap_value(self.wrapped_data.get_argument(key)) def __setitem__(self, idx, value): self.wrapped_data.set_argument(idx, entity_instance.map_value(value)) def __len__(self): return len(self.wrapped_data) @@ -63,6 +68,8 @@ class file: return [entity_instance(e) for e in self.wrapped_data.by_type(type)] def write(self, fn): self.wrapped_data.write(fn) + def __iter__(self): + return iter(self[id] for id in self.wrapped_data.entity_names()) class guid: