mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-26 18:21:59 +00:00
Fix #180
This commit is contained in:
@@ -28,11 +28,11 @@ class file(object):
|
|||||||
self.wrapped_data = f or ifcopenshell_wrapper.file()
|
self.wrapped_data = f or ifcopenshell_wrapper.file()
|
||||||
def create_entity(self,type,*args,**kwargs):
|
def create_entity(self,type,*args,**kwargs):
|
||||||
e = entity_instance(type)
|
e = entity_instance(type)
|
||||||
|
self.wrapped_data.add(e.wrapped_data)
|
||||||
|
e.wrapped_data.this.disown()
|
||||||
attrs = list(enumerate(args)) + \
|
attrs = list(enumerate(args)) + \
|
||||||
[(e.wrapped_data.get_argument_index(name), arg) for name, arg in kwargs.items()]
|
[(e.wrapped_data.get_argument_index(name), arg) for name, arg in kwargs.items()]
|
||||||
for idx, arg in attrs: e[idx] = arg
|
for idx, arg in attrs: e[idx] = arg
|
||||||
self.wrapped_data.add(e.wrapped_data)
|
|
||||||
e.wrapped_data.this.disown()
|
|
||||||
return e
|
return e
|
||||||
def __getattr__(self, attr):
|
def __getattr__(self, attr):
|
||||||
if attr[0:6] == 'create': return functools.partial(self.create_entity,attr[6:])
|
if attr[0:6] == 'create': return functools.partial(self.create_entity,attr[6:])
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ private:
|
|||||||
IfcSpfHeader _header;
|
IfcSpfHeader _header;
|
||||||
|
|
||||||
void setDefaultHeaderValues();
|
void setDefaultHeaderValues();
|
||||||
void register_inverse(unsigned, Token);
|
|
||||||
public:
|
public:
|
||||||
IfcParse::IfcSpfLexer* tokens;
|
IfcParse::IfcSpfLexer* tokens;
|
||||||
IfcParse::IfcSpfStream* stream;
|
IfcParse::IfcSpfStream* stream;
|
||||||
@@ -130,6 +130,10 @@ public:
|
|||||||
|
|
||||||
void load(const IfcEntityInstanceData&);
|
void load(const IfcEntityInstanceData&);
|
||||||
void load(unsigned entity_instance_name, std::vector<Argument*>& attributes);
|
void load(unsigned entity_instance_name, std::vector<Argument*>& attributes);
|
||||||
|
|
||||||
|
void register_inverse(unsigned, Token);
|
||||||
|
void register_inverse(unsigned, IfcUtil::IfcBaseClass*);
|
||||||
|
void unregister_inverse(unsigned, IfcUtil::IfcBaseClass*);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+121
-23
@@ -915,6 +915,20 @@ void IfcParse::IfcFile::register_inverse(unsigned id_from, Token t) {
|
|||||||
byref[t.value_int].push_back(id_from);
|
byref[t.value_int].push_back(id_from);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IfcParse::IfcFile::register_inverse(unsigned id_from, IfcUtil::IfcBaseClass* inst) {
|
||||||
|
byref[inst->entity->id()].push_back(id_from);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IfcParse::IfcFile::unregister_inverse(unsigned id_from, IfcUtil::IfcBaseClass* inst) {
|
||||||
|
std::vector<unsigned int>& ids = byref[inst->entity->id()];
|
||||||
|
std::vector<unsigned int>::const_iterator it = std::find(ids.begin(), ids.end(), id_from);
|
||||||
|
if (it == ids.end()) {
|
||||||
|
throw IfcParse::IfcException("Instance not found among inverses");
|
||||||
|
} else {
|
||||||
|
ids.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Returns a string representation of the entity
|
// Returns a string representation of the entity
|
||||||
// Note that this initializes the entity if it is not initialized
|
// Note that this initializes the entity if it is not initialized
|
||||||
@@ -1008,6 +1022,97 @@ Argument* IfcEntityInstanceData::getArgument(unsigned int i) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class unregister_inverse_visitor {
|
||||||
|
private:
|
||||||
|
IfcFile& file_;
|
||||||
|
const IfcEntityInstanceData& data_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
unregister_inverse_visitor(IfcFile& file, const IfcEntityInstanceData& data)
|
||||||
|
: file_(file), data_(data)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void operator()(IfcUtil::IfcBaseClass* inst) {
|
||||||
|
file_.unregister_inverse(data_.id(), inst);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class register_inverse_visitor {
|
||||||
|
private:
|
||||||
|
IfcFile& file_;
|
||||||
|
const IfcEntityInstanceData& data_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
register_inverse_visitor(IfcFile& file, const IfcEntityInstanceData& data)
|
||||||
|
: file_(file), data_(data)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void operator()(IfcUtil::IfcBaseClass* inst) {
|
||||||
|
file_.register_inverse(data_.id(), inst);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class add_to_instance_list_visitor {
|
||||||
|
private:
|
||||||
|
IfcEntityList::ptr& list_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
add_to_instance_list_visitor(IfcEntityList::ptr& list)
|
||||||
|
: list_(list)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void operator()(IfcUtil::IfcBaseClass* inst) {
|
||||||
|
list_->push(inst);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class apply_individual_instance_visitor {
|
||||||
|
private:
|
||||||
|
Argument* attribute_;
|
||||||
|
IfcEntityInstanceData* data_;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void apply_attribute_(T& t, Argument* attr) const {
|
||||||
|
if (attr->type() == IfcUtil::Argument_ENTITY_INSTANCE) {
|
||||||
|
IfcUtil::IfcBaseClass* inst = *attr;
|
||||||
|
t(inst);
|
||||||
|
} else if (attr->type() == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
|
||||||
|
IfcEntityList::ptr entity_list_attribute = *attr;
|
||||||
|
for (IfcEntityList::it it = entity_list_attribute->begin(); it != entity_list_attribute->end(); ++it) {
|
||||||
|
t(*it);
|
||||||
|
}
|
||||||
|
} else if (attr->type() == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) {
|
||||||
|
IfcEntityListList::ptr entity_list_attribute = *attr;
|
||||||
|
for (IfcEntityListList::outer_it it = entity_list_attribute->begin(); it != entity_list_attribute->end(); ++it) {
|
||||||
|
for (IfcEntityListList::inner_it jt = it->begin(); jt != it->end(); ++jt) {
|
||||||
|
t(*jt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
apply_individual_instance_visitor(Argument* attribute)
|
||||||
|
: attribute_(attribute), data_(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
apply_individual_instance_visitor(IfcEntityInstanceData* data)
|
||||||
|
: attribute_(0), data_(data)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void apply(T& t) const {
|
||||||
|
if (attribute_) {
|
||||||
|
apply_attribute_(t, attribute_);
|
||||||
|
} else {
|
||||||
|
for (unsigned i = 0; i < data_->getArgumentCount(); ++i) {
|
||||||
|
Argument* attr = data_->getArgument(i);
|
||||||
|
apply_attribute_(t, attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
void IfcEntityInstanceData::setArgument(unsigned int i, Argument* a, IfcUtil::ArgumentType attr_type) {
|
void IfcEntityInstanceData::setArgument(unsigned int i, Argument* a, IfcUtil::ArgumentType attr_type) {
|
||||||
if (!initialized_) {
|
if (!initialized_) {
|
||||||
load();
|
load();
|
||||||
@@ -1017,10 +1122,6 @@ void IfcEntityInstanceData::setArgument(unsigned int i, Argument* a, IfcUtil::Ar
|
|||||||
attributes_.push_back(new NullArgument());
|
attributes_.push_back(new NullArgument());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < attributes_.size()) {
|
|
||||||
delete attributes_[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attr_type == IfcUtil::Argument_UNKNOWN) {
|
if (attr_type == IfcUtil::Argument_UNKNOWN) {
|
||||||
attr_type = a->type();
|
attr_type = a->type();
|
||||||
}
|
}
|
||||||
@@ -1117,6 +1218,20 @@ void IfcEntityInstanceData::setArgument(unsigned int i, Argument* a, IfcUtil::Ar
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i < attributes_.size()) {
|
||||||
|
Argument* current_attribute = attributes_[i];
|
||||||
|
if (this->file) {
|
||||||
|
unregister_inverse_visitor visitor(*this->file, *this);
|
||||||
|
apply_individual_instance_visitor(current_attribute).apply(visitor);
|
||||||
|
}
|
||||||
|
delete attributes_[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->file) {
|
||||||
|
register_inverse_visitor visitor(*this->file, *this);
|
||||||
|
apply_individual_instance_visitor(copy).apply(visitor);
|
||||||
|
}
|
||||||
|
|
||||||
if (i < attributes_.size()) {
|
if (i < attributes_.size()) {
|
||||||
attributes_[i] = copy;
|
attributes_[i] = copy;
|
||||||
} else {
|
} else {
|
||||||
@@ -1271,25 +1386,8 @@ void traverse_(IfcUtil::IfcBaseClass* instance, std::set<IfcUtil::IfcBaseClass*>
|
|||||||
|
|
||||||
if (level >= max_level && max_level > 0) return;
|
if (level >= max_level && max_level > 0) return;
|
||||||
|
|
||||||
for (unsigned i = 0; i < instance->getArgumentCount(); ++i) {
|
add_to_instance_list_visitor visit(list);
|
||||||
Argument* arg = instance->getArgument(i);
|
apply_individual_instance_visitor(instance->entity).apply(visit);
|
||||||
|
|
||||||
if (arg->type() == IfcUtil::Argument_ENTITY_INSTANCE) {
|
|
||||||
traverse_(*arg, visited, list, level + 1, max_level);
|
|
||||||
} else if (arg->type() == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
|
|
||||||
IfcEntityList::ptr entity_list_attribute = *arg;
|
|
||||||
for (IfcEntityList::it it = entity_list_attribute->begin(); it != entity_list_attribute->end(); ++it) {
|
|
||||||
traverse_(*it, visited, list, level + 1, max_level);
|
|
||||||
}
|
|
||||||
} else if (arg->type() == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) {
|
|
||||||
IfcEntityListList::ptr entity_list_attribute = *arg;
|
|
||||||
for (IfcEntityListList::outer_it it = entity_list_attribute->begin(); it != entity_list_attribute->end(); ++it) {
|
|
||||||
for (IfcEntityListList::inner_it jt = it->begin(); jt != it->end(); ++jt) {
|
|
||||||
traverse_(*jt, visited, list, level + 1, max_level);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcEntityList::ptr IfcParse::traverse(IfcUtil::IfcBaseClass* instance, int max_level) {
|
IfcEntityList::ptr IfcParse::traverse(IfcUtil::IfcBaseClass* instance, int max_level) {
|
||||||
|
|||||||
@@ -52,6 +52,16 @@ f[22].MiddleNames = 'John', 'Matthew'
|
|||||||
assert "('John','Matthew')" in str(f[22])
|
assert "('John','Matthew')" in str(f[22])
|
||||||
assert ("Id", "123") in list(f[22].get_info().items())
|
assert ("Id", "123") in list(f[22].get_info().items())
|
||||||
|
|
||||||
|
# Assignment of instances and implications on inverse attributes
|
||||||
|
assert f[288].ConnectedTo[0].RelatingElement == f[288]
|
||||||
|
num_connections_1 = len(f[340].ConnectedTo + f[340].ConnectedFrom)
|
||||||
|
f[288].ConnectedTo[0].RelatingElement = f[340]
|
||||||
|
num_connections_2 = len(f[340].ConnectedTo + f[340].ConnectedFrom)
|
||||||
|
assert num_connections_2 == num_connections_1 + 1
|
||||||
|
assert f[288].ConnectedTo == ()
|
||||||
|
rel = f.createIfcRelConnectsPathElements(RelatingElement=f[288])
|
||||||
|
assert f[288].ConnectedTo == (rel,)
|
||||||
|
|
||||||
# Some operations on ifcopenshell.guid
|
# Some operations on ifcopenshell.guid
|
||||||
assert len(ifcopenshell.guid.compress(uuid.uuid1().hex)) == 22
|
assert len(ifcopenshell.guid.compress(uuid.uuid1().hex)) == 22
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user