From 2fd2b49709f7d82a44b99dc713a61c6840e03653 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 27 Jun 2021 11:14:26 +0200 Subject: [PATCH] #1539 Option to specify id/instance_name in file::add() --- src/ifcopenshell-python/ifcopenshell/file.py | 10 +- src/ifcparse/IfcFile.h | 2 +- src/ifcparse/IfcParse.cpp | 119 +++++++++++-------- 3 files changed, 76 insertions(+), 55 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/file.py b/src/ifcopenshell-python/ifcopenshell/file.py index cb98e3b79e..0bf9344c80 100644 --- a/src/ifcopenshell-python/ifcopenshell/file.py +++ b/src/ifcopenshell-python/ifcopenshell/file.py @@ -80,8 +80,12 @@ class file(object): f.create_entity('IfcPerson', Identification='Foobar') >>> #3=IfcPerson('Foobar',$,$,$,$,$,$,$) """ + eid = -1 + try: + eid = kwargs.pop("_id", -1) + except: pass e = entity_instance((self.schema, type)) - self.wrapped_data.add(e.wrapped_data) + self.wrapped_data.add(e.wrapped_data, eid) e.wrapped_data.this.disown() attrs = list(enumerate(args)) + [(e.wrapped_data.get_argument_index(name), arg) for name, arg in kwargs.items()] for idx, arg in attrs: @@ -120,12 +124,12 @@ class file(object): """ return self[guid] - def add(self, inst): + def add(self, inst, _id=None): """Adds an entity including any dependent entities to an IFC file. If the entity already exists, it is not re-added.""" inst.wrapped_data.this.disown() - return entity_instance(self.wrapped_data.add(inst.wrapped_data)) + return entity_instance(self.wrapped_data.add(inst.wrapped_data, -1 if _id is None else _id)) def by_type(self, type, include_subtypes=True): """Return IFC objects filtered by IFC Type and wrapped with the entity_instance class. diff --git a/src/ifcparse/IfcFile.h b/src/ifcparse/IfcFile.h index 189de813f8..f22a042e1b 100644 --- a/src/ifcparse/IfcFile.h +++ b/src/ifcparse/IfcFile.h @@ -230,7 +230,7 @@ public: void recalculate_id_counter(); - IfcUtil::IfcBaseClass* addEntity(IfcUtil::IfcBaseClass* entity); + IfcUtil::IfcBaseClass* addEntity(IfcUtil::IfcBaseClass* entity, int id=-1); void addEntities(IfcEntityList::ptr es); void batch() { batch_mode_ = true; } diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index bd8acce028..b59ac0c887 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -1562,7 +1562,11 @@ void IfcFile::addEntities(IfcEntityList::ptr es) { } } -IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) { +IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id) { + if (id != -1 && byid.find((unsigned)id) != byid.end()) { + throw IfcParse::IfcException("An instance with id " + boost::lexical_cast(id) + " is already part of this file"); + } + if (entity->declaration().schema() != schema()) { throw IfcParse::IfcException("Unabled to add instance from " + entity->declaration().schema()->name() + " schema to file with " + schema()->name() + " schema"); } @@ -1698,7 +1702,14 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) { // the instance is pointed to this file. we->file = this; if (we->type()->as_entity()) { - we->set_id(FreshId()); + if (id == -1) { + we->set_id(FreshId()); + } else { + we->set_id((unsigned int)id); + if ((unsigned) id > MaxId) { + MaxId = (unsigned)id; + } + } } // @todo entity_file_map: use weak_ptr @@ -1720,62 +1731,68 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) { } } -// The mapping by entity type is updated. -const IfcParse::declaration* ty = &new_entity->declaration(); + // The mapping by entity type is updated. + const IfcParse::declaration* ty = &new_entity->declaration(); -if (ty->as_entity()) { - IfcEntityList::ptr insts = instances_by_type_excl_subtypes(ty); - if (!insts) { - insts = IfcEntityList::ptr(new IfcEntityList()); - bytype_excl[ty] = insts; - } - insts->push(new_entity); -} - -for (; ty->as_entity();) { - IfcEntityList::ptr insts = instances_by_type(ty); - if (!insts) { - insts = IfcEntityList::ptr(new IfcEntityList()); - bytype[ty] = insts; - } - insts->push(new_entity); - - const IfcParse::declaration* pt = ty->as_entity()->supertype(); - if (pt) { - ty = pt; - } - else { - break; - } -} - -if (ty->as_entity()) { - int new_id = -1; - if (!new_entity->data().file) { - // For newly created entities ensure a valid ENTITY_INSTANCE_NAME is set - new_entity->data().file = this; - new_id = new_entity->data().set_id(); - } - else { - new_id = new_entity->data().id(); + if (ty->as_entity()) { + IfcEntityList::ptr insts = instances_by_type_excl_subtypes(ty); + if (!insts) { + insts = IfcEntityList::ptr(new IfcEntityList()); + bytype_excl[ty] = insts; + } + insts->push(new_entity); } - if (byid.find(new_id) != byid.end()) { - // This should not happen - std::stringstream ss; - ss << "Overwriting entity with id " << new_id; - Logger::Message(Logger::LOG_WARNING, ss.str()); + for (; ty->as_entity();) { + IfcEntityList::ptr insts = instances_by_type(ty); + if (!insts) { + insts = IfcEntityList::ptr(new IfcEntityList()); + bytype[ty] = insts; + } + insts->push(new_entity); + + const IfcParse::declaration* pt = ty->as_entity()->supertype(); + if (pt) { + ty = pt; + } + else { + break; + } } - // The mapping by entity instance name is updated. - byid[new_id] = new_entity; -} + if (ty->as_entity()) { + int new_id = -1; + if (!new_entity->data().file) { + // For newly created entities ensure a valid ENTITY_INSTANCE_NAME is set + new_entity->data().file = this; + boost::optional id_value; + if (id != -1) { + id_value = (unsigned)id; + if ((unsigned)id > MaxId) { + MaxId = (unsigned)id; + } + } + new_id = new_entity->data().set_id(id_value); + } else { + new_id = new_entity->data().id(); + } -if (parsing_complete_ && ty->as_entity()) { - build_inverses_(new_entity); -} + if (byid.find(new_id) != byid.end()) { + // This should not happen + std::stringstream ss; + ss << "Overwriting entity with id " << new_id; + Logger::Message(Logger::LOG_WARNING, ss.str()); + } -return new_entity; + // The mapping by entity instance name is updated. + byid[new_id] = new_entity; + } + + if (parsing_complete_ && ty->as_entity()) { + build_inverses_(new_entity); + } + + return new_entity; } void IfcFile::removeEntity(IfcUtil::IfcBaseClass* entity) {