This commit is contained in:
Thomas Krijnen
2024-08-20 20:21:35 +02:00
parent 9c323f91dd
commit 261fb895eb
16 changed files with 273 additions and 467 deletions
+1 -1
View File
@@ -1505,7 +1505,7 @@ namespace latebound_access {
IfcUtil::IfcBaseClass* create(IfcParse::IfcFile& f, const std::string& entity) { IfcUtil::IfcBaseClass* create(IfcParse::IfcFile& f, const std::string& entity) {
auto decl = f.schema()->declaration_by_name(entity); auto decl = f.schema()->declaration_by_name(entity);
auto data = IfcEntityInstanceData(storage_t(decl->as_entity()->attribute_count())); auto data = IfcEntityInstanceData(storage_t(decl->as_entity()->attribute_count()));
auto inst = f.schema()->instantiate(entity, std::move(data)); auto inst = f.schema()->instantiate(decl, std::move(data));
if (decl->is("IfcRoot")) { if (decl->is("IfcRoot")) {
IfcParse::IfcGlobalId guid; IfcParse::IfcGlobalId guid;
latebound_access::set(inst, "GlobalId", (std::string) guid); latebound_access::set(inst, "GlobalId", (std::string) guid);
+2
View File
@@ -55,6 +55,8 @@
* * * *
********************************************************************************/ ********************************************************************************/
#define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR
#ifndef IFCGEOMITERATOR_H #ifndef IFCGEOMITERATOR_H
#define IFCGEOMITERATOR_H #define IFCGEOMITERATOR_H
+5 -8
View File
@@ -87,19 +87,16 @@ class IFC_PARSE_API IfcBaseInterface {
class IFC_PARSE_API IfcBaseClass : public virtual IfcBaseInterface { class IFC_PARSE_API IfcBaseClass : public virtual IfcBaseInterface {
protected: protected:
uint32_t identity_;
static std::atomic_uint32_t counter_; static std::atomic_uint32_t counter_;
IfcEntityInstanceData data_; uint32_t identity_;
public:
static bool is_null(const IfcBaseClass* not_this) {
return not_this == nullptr;
}
public:
uint32_t id_; uint32_t id_;
IfcParse::IfcFile* file_; IfcParse::IfcFile* file_;
protected:
IfcEntityInstanceData data_;
public:
IfcBaseClass(IfcEntityInstanceData&& data) IfcBaseClass(IfcEntityInstanceData&& data)
: identity_(counter_++) : identity_(counter_++)
, data_(std::move(data)) , data_(std::move(data))
+24 -2
View File
@@ -419,14 +419,36 @@ std::wstring IfcUtil::convert_utf8(const std::string& string) {
// bug in msvc 2015 and 2017, unsure if fixed in later versions // bug in msvc 2015 and 2017, unsure if fixed in later versions
std::u32string IfcUtil::convert_utf8_to_utf32(const std::string& s) { std::u32string IfcUtil::convert_utf8_to_utf32(const std::string& s) {
bool is_ascii = true;
for (char c : s) {
if (static_cast<unsigned char>(c) >= 128) {
is_ascii = false;
break;
}
}
if (is_ascii) {
return std::u32string(s.begin(), s.end());
} else {
auto converted = std::wstring_convert<std::codecvt_utf8<int32_t>, int32_t>().from_bytes(s); auto converted = std::wstring_convert<std::codecvt_utf8<int32_t>, int32_t>().from_bytes(s);
return std::u32string(reinterpret_cast<char32_t const*>(converted.data())); return std::u32string(reinterpret_cast<char32_t const*>(converted.data()));
}
} }
#else #else
std::u32string IfcUtil::convert_utf8_to_utf32(const std::string& string) { std::u32string IfcUtil::convert_utf8_to_utf32(const std::string& s) {
return std::wstring_convert<std::codecvt_utf8<std::u32string::value_type>, std::u32string::value_type>().from_bytes(string); bool is_ascii = true;
for (char c : s) {
if (static_cast<unsigned char>(c) >= 128) {
is_ascii = false;
break;
}
}
if (is_ascii) {
return std::u32string(s.begin(), s.end());
} else {
return std::wstring_convert<std::codecvt_utf8<std::u32string::value_type>, std::u32string::value_type>().from_bytes(s);
}
} }
#endif #endif
+4
View File
@@ -167,6 +167,10 @@ class IFC_PARSE_API IfcEntityInstanceData {
: storage_(std::move(storage)) : storage_(std::move(storage))
{} {}
IfcEntityInstanceData(IfcEntityInstanceData&& other) noexcept
: storage_(std::move(other.storage_))
{}
IfcEntityInstanceData(const IfcEntityInstanceData& data); IfcEntityInstanceData(const IfcEntityInstanceData& data);
IfcEntityInstanceData& operator=(IfcEntityInstanceData&& other) { IfcEntityInstanceData& operator=(IfcEntityInstanceData&& other) {
+55 -56
View File
@@ -141,7 +141,7 @@ namespace {
} else if (t.type == IfcParse::Token_FLOAT) { } else if (t.type == IfcParse::Token_FLOAT) {
fn(IfcParse::TokenFunc::asFloat(t)); fn(IfcParse::TokenFunc::asFloat(t));
} else if (t.type == IfcParse::Token_IDENTIFIER) { } else if (t.type == IfcParse::Token_IDENTIFIER) {
fn(InstanceReference{ IfcParse::TokenFunc::asIdentifier(t) }); fn(IfcParse::reference_or_simple_type{ InstanceReference{ IfcParse::TokenFunc::asIdentifier(t) } });
} else if (t.type == IfcParse::Token_INT) { } else if (t.type == IfcParse::Token_INT) {
fn(IfcParse::TokenFunc::asInt(t)); fn(IfcParse::TokenFunc::asInt(t));
} else if (t.type == IfcParse::Token_STRING) { } else if (t.type == IfcParse::Token_STRING) {
@@ -150,27 +150,32 @@ namespace {
} }
template <typename Fn> template <typename Fn>
void construct_(IfcParse::parse_context& p, Fn fn) { void construct_(IfcParse::parse_context& p, const IfcParse::aggregation_type* aggr, Fn fn) {
if (p.tokens_.empty()) { if (p.tokens_.empty()) {
// @todo based on type create appropate empty aggregate // @todo instead of ugly if-else we could also default initialize the respective
// variant types below.
if (aggr) {
auto aggr_type = IfcUtil::make_aggregate(IfcUtil::from_parameter_type(aggr->type_of_element()));
if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_INT) {
fn(std::vector<int>{});
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) {
fn(std::vector<double>{});
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_STRING) {
fn(std::vector<std::string>{});
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_BINARY) {
fn(std::vector<boost::dynamic_bitset<>>{});
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
fn(aggregate_of_instance::ptr(new aggregate_of_instance));
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT) {
fn(std::vector<std::vector<int>>{});
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE) {
fn(std::vector<std::vector<double>>{});
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) {
fn(aggregate_of_aggregate_of_instance::ptr(new aggregate_of_aggregate_of_instance));
}
}
return; return;
} }
decltype(p.tokens_) p_tokens_filtered;
std::vector<uint8_t> first_type;
get_token_type(first_type, p.tokens_.front());
std::copy_if(
p.tokens_.begin(),
p.tokens_.end(),
std::back_inserter(p_tokens_filtered),
[first_type](auto& x) {
std::vector<uint8_t> nth_type;
get_token_type(nth_type, x);
return can_coerce(first_type, nth_type);
}
);
if (p.tokens_.size() != p_tokens_filtered.size()) {
// warning
}
typedef boost::variant< typedef boost::variant<
Blank, Blank,
@@ -188,25 +193,28 @@ namespace {
possible_aggregation_types_t aggregate_storage; possible_aggregation_types_t aggregate_storage;
for (auto& t : p_tokens_filtered) { auto append_to_aggregate_storage = [&aggregate_storage](auto v) {
boost::apply_visitor([&aggregate_storage](auto& v) { if constexpr (is_type_in_variant_v<possible_aggregation_types_t, std::vector<std::decay_t<decltype(v)>>>) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::Token>) {
// @todo get aggregate of enumeration
dispatch_token(v, nullptr, [&aggregate_storage](auto v) {
if constexpr (std::is_same_v<decltype(v), InstanceReference>) {
if (aggregate_storage.which() == 0) {
aggregate_storage = std::vector<IfcParse::reference_or_simple_type>{ v };
} else {
boost::get< std::vector<IfcParse::reference_or_simple_type>>(aggregate_storage).push_back(v);
}
} else if constexpr (is_type_in_variant_v<possible_aggregation_types_t, std::vector<std::decay_t<decltype(v)>>>) {
if (aggregate_storage.which() == 0) { if (aggregate_storage.which() == 0) {
aggregate_storage = std::vector<std::decay_t<decltype(v)>>{ v }; aggregate_storage = std::vector<std::decay_t<decltype(v)>>{ v };
} else { } else {
boost::get< std::vector<std::decay_t<decltype(v)>>>(aggregate_storage).push_back(v); auto* vec_ptr = boost::get< std::vector<std::decay_t<decltype(v)>>>(&aggregate_storage);
if (vec_ptr) {
vec_ptr->push_back(v);
} else {
// inconsistent aggregate valuation
} }
} }
}); } else {
// unsupported aggregate type
}
};
for (auto& t : p.tokens_) {
boost::apply_visitor([&aggregate_storage, &append_to_aggregate_storage, aggr](auto& v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::Token>) {
// @todo get aggregate of enumeration
dispatch_token(v, aggr && aggr->type_of_element()->as_named_type() ? aggr->type_of_element()->as_named_type()->declared_type() : nullptr, append_to_aggregate_storage);
} else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::parse_context*>) { } else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::parse_context*>) {
/*construct_(*v, [&aggregate_storage](auto& v) { /*construct_(*v, [&aggregate_storage](auto& v) {
if (aggregate_storage.which() == 0) { if (aggregate_storage.which() == 0) {
@@ -217,11 +225,7 @@ namespace {
});*/ });*/
// Too deeply nested list // Too deeply nested list
} else { } else {
if (aggregate_storage.which() == 0) { append_to_aggregate_storage(v);
aggregate_storage = std::vector<IfcParse::reference_or_simple_type>{ v };
} else {
boost::get<std::vector<IfcParse::reference_or_simple_type>>(aggregate_storage).push_back(v);
}
} }
}, t); }, t);
} }
@@ -247,16 +251,7 @@ IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_re
); );
} }
std::vector<IfcUtil::ArgumentType> attr_types; if (decl && (tokens_.size() != parameter_types.size())) {
std::transform(
parameter_types.begin(),
parameter_types.end(),
std::back_inserter(attr_types),
IfcUtil::from_parameter_type
);
if (decl && (tokens_.size() != attr_types.size())) {
// warning // warning
} }
@@ -265,17 +260,15 @@ IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_re
} }
storage_t storage(decl storage_t storage(decl
? (std::min)(attr_types.size(), tokens_.size()) ? (std::min)(parameter_types.size(), tokens_.size())
: tokens_.size() : tokens_.size()
); );
auto it = tokens_.begin(); auto it = tokens_.begin();
auto jt = attr_types.begin();
auto kt = parameter_types.begin(); auto kt = parameter_types.begin();
for (; it != tokens_.end() && (!decl || jt != attr_types.end()); ++it) { for (; it != tokens_.end() && (!decl || kt != parameter_types.end()); ++it) {
auto& token = *it; auto& token = *it;
// @todo coerce to expected type, e.g empty -> std::vector<int>, bool -> logical // @todo coerce to expected type, e.g empty -> std::vector<int>, bool -> logical
// auto& attr_type = *jt;
const IfcParse::parameter_type* param_type = nullptr; const IfcParse::parameter_type* param_type = nullptr;
if (decl) { if (decl) {
param_type = *kt; param_type = *kt;
@@ -286,20 +279,26 @@ IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_re
boost::apply_visitor([this, &storage, name, &references_to_resolve, index, it, param_type](auto& v) { boost::apply_visitor([this, &storage, name, &references_to_resolve, index, it, param_type](auto& v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::Token>) { if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::Token>) {
dispatch_token(v, param_type && param_type->as_named_type() ? param_type->as_named_type()->declared_type() : nullptr, [this, &storage, name, &references_to_resolve, index](auto v) { dispatch_token(v, param_type && param_type->as_named_type() ? param_type->as_named_type()->declared_type() : nullptr, [this, &storage, name, &references_to_resolve, index](auto v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, InstanceReference>) { if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::reference_or_simple_type>) {
references_to_resolve.push_back(std::make_pair( references_to_resolve.push_back(std::make_pair(
// @todo previously this was storage but apparently the // @todo previously this was storage but apparently the
// pointer is not constant with the moving and temporary nature // pointer is not constant with the moving and temporary nature
// maybe it ought to be and in that case a pointer is more direct // maybe it ought to be and in that case a pointer is more direct
MutableAttributeValue{ name, index }, MutableAttributeValue{ name, index },
unresolved_references::value_type::second_type{v} v
)); ));
} else { } else {
storage.set(index, v); storage.set(index, v);
} }
}); });
} else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::parse_context*>) { } else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::parse_context*>) {
construct_(*v, [this, &storage, name, &references_to_resolve, index](auto& v) { auto pt = param_type;
if (pt) {
while (pt->as_named_type()) {
pt = pt->as_named_type()->declared_type()->as_type_declaration()->declared_type();
}
}
construct_(*v, pt ? pt->as_aggregation_type() : nullptr, [this, &storage, name, &references_to_resolve, index](const auto& v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<reference_or_simple_type>>) { if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<reference_or_simple_type>>) {
references_to_resolve.push_back({ {name, index }, v }); references_to_resolve.push_back({ {name, index }, v });
} else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<std::vector<reference_or_simple_type>>>) { } else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<std::vector<reference_or_simple_type>>>) {
@@ -314,7 +313,7 @@ IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_re
}, token); }, token);
if (decl) { if (decl) {
++jt, ++kt; ++kt;
} }
} }
+6 -6
View File
@@ -104,7 +104,7 @@ class IFC_PARSE_API IfcFile {
typedef boost::unordered_map<unsigned int, IfcUtil::IfcBaseClass*> entity_by_id_t; typedef boost::unordered_map<unsigned int, IfcUtil::IfcBaseClass*> entity_by_id_t;
typedef boost::unordered_map<uint32_t, IfcUtil::IfcBaseClass*> entity_by_iden_t; typedef boost::unordered_map<uint32_t, IfcUtil::IfcBaseClass*> entity_by_iden_t;
typedef std::map<std::string, IfcUtil::IfcBaseClass*> entity_by_guid_t; typedef std::map<std::string, IfcUtil::IfcBaseClass*> entity_by_guid_t;
typedef std::tuple<int, int, int> inverse_attr_record; typedef std::tuple<int, short, short> inverse_attr_record;
enum INVERSE_ATTR { enum INVERSE_ATTR {
INSTANCE_ID, INSTANCE_ID,
INSTANCE_TYPE, INSTANCE_TYPE,
@@ -165,10 +165,10 @@ class IFC_PARSE_API IfcFile {
entity_by_id_t byid_; entity_by_id_t byid_;
// this is for simple types // this is for simple types
entity_by_iden_t byidentity_; entity_by_iden_t byidentity_;
entities_by_type_t bytype_; // entities_by_type_t bytype_;
entities_by_type_t bytype_excl_; entities_by_type_t bytype_excl_;
entities_by_ref_t byref_; // entities_by_ref_t byref_;
entities_by_ref_excl_t byref_excl_; entities_by_ref_t byref_excl_;
entity_by_guid_t byguid_; entity_by_guid_t byguid_;
entity_entity_map_t entity_file_map_; entity_entity_map_t entity_file_map_;
@@ -222,8 +222,8 @@ class IFC_PARSE_API IfcFile {
type_iterator types_begin() const; type_iterator types_begin() const;
type_iterator types_end() const; type_iterator types_end() const;
type_iterator types_incl_super_begin() const; // type_iterator types_incl_super_begin() const;
type_iterator types_incl_super_end() const; // type_iterator types_incl_super_end() const;
/// Returns all entities in the file that match the template argument. /// Returns all entities in the file that match the template argument.
/// NOTE: This also returns subtypes of the requested type, for example: /// NOTE: This also returns subtypes of the requested type, for example:
+1 -1
View File
@@ -446,7 +446,7 @@ class IFC_PARSE_API IfcHierarchyHelper : public IfcParse::IfcFile {
data.storage_.set(relating_index, relating_object); data.storage_.set(relating_index, relating_object);
data.storage_.set(related_index, related_objects); data.storage_.set(related_index, related_objects);
T* t = (T*)Schema::get_schema().instantiate(T::Class().name(), std::move(data)); T* t = (T*)Schema::get_schema().instantiate(&T::Class(), std::move(data));
addEntity(t); addEntity(t);
} }
} }
+9 -3
View File
@@ -17,6 +17,8 @@
* * * *
********************************************************************************/ ********************************************************************************/
#define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR
#include "IfcLogger.h" #include "IfcLogger.h"
#include "Argument.h" #include "Argument.h"
@@ -147,8 +149,12 @@ void Logger::SetOutput(std::wostream* stream1, std::wostream* stream2) {
} }
void Logger::Message(Logger::Severity type, const std::string& message, const IfcUtil::IfcBaseInterface* instance) { void Logger::Message(Logger::Severity type, const std::string& message, const IfcUtil::IfcBaseInterface* instance) {
// static std::mutex mtx; if (type < verbosity_) {
// std::lock_guard<std::mutex> lock(mtx); return;
}
static std::mutex mtx;
std::lock_guard<std::mutex> lock(mtx);
if (type == LOG_PERF) { if (type == LOG_PERF) {
if (!first_timepoint_) { if (!first_timepoint_) {
@@ -166,7 +172,7 @@ void Logger::Message(Logger::Severity type, const std::string& message, const If
if (type > max_severity_) { if (type > max_severity_) {
max_severity_ = type; max_severity_ = type;
} }
if (((log2_ != nullptr) || (wlog2_ != nullptr)) && type >= verbosity_) { if (((log2_ != nullptr) || (wlog2_ != nullptr))) {
if (format_ == FMT_PLAIN) { if (format_ == FMT_PLAIN) {
if (log2_ != nullptr) { if (log2_ != nullptr) {
plain_text_message(*log2_, current_product_, type, message, instance); plain_text_message(*log2_, current_product_, type, message, instance);
+89 -341
View File
@@ -693,27 +693,6 @@ void IfcParse::IfcFile::load(unsigned entity_instance_name, const IfcParse::enti
next = tokens->Next(); next = tokens->Next();
} }
/*
std::vector<Argument*>* vector = 0;
vector_or_array<Argument*> filler(attributes, num_attributes);
if (attributes == 0) {
if (num_attributes != 0) {
// If num_attributes is zero we know this is a top-level entity instance (or header entity) being parsed.
// There can only be parsed one of these at a time, so we can reuse the vector we have defined at the file
// scope.
if (entity != nullptr) {
vector = &internal_attribute_vector_;
} else {
vector = &internal_attribute_vector_simple_type_;
}
vector->clear();
} else {
vector = new std::vector<Argument*>;
}
filler = vector_or_array<Argument*>(vector);
}
*/
size_t attribute_index_within_data = 0; size_t attribute_index_within_data = 0;
size_t return_value = 0; size_t return_value = 0;
@@ -737,7 +716,8 @@ void IfcParse::IfcFile::load(unsigned entity_instance_name, const IfcParse::enti
try { try {
parse_context ps; parse_context ps;
load(0, nullptr, ps, -1); load(0, nullptr, ps, -1);
auto* simple_type_instance = schema_->instantiate(TokenFunc::asStringRef(next), ps.construct(-1, references_to_resolve, schema_->declaration_by_name(TokenFunc::asStringRef(next)))); auto decl = schema_->declaration_by_name(TokenFunc::asStringRef(next));
auto* simple_type_instance = schema_->instantiate(decl, ps.construct(-1, references_to_resolve, decl));
//@todo decide addEntity(((IfcUtil::IfcBaseClass*)*entity)); //@todo decide addEntity(((IfcUtil::IfcBaseClass*)*entity));
context.push(simple_type_instance); context.push(simple_type_instance);
simple_type_instance->file_ = this; simple_type_instance->file_ = this;
@@ -766,10 +746,6 @@ IfcEntityInstanceData IfcParse::read(unsigned int i, IfcFile* f) {
parse_context pc; parse_context pc;
f->load(i, ty->as_entity(), pc, -1); f->load(i, ty->as_entity(), pc, -1);
return IfcEntityInstanceData(pc.construct(i, f->references_to_resolve, ty)); return IfcEntityInstanceData(pc.construct(i, f->references_to_resolve, ty));
/*std::ostringstream oss;
d.toString(oss);
auto osss = oss.str();
std::wcout << osss.c_str() << std::endl;*/
} }
void IfcParse::IfcFile::try_read_semicolon() { void IfcParse::IfcFile::try_read_semicolon() {
@@ -783,37 +759,16 @@ void IfcParse::IfcFile::try_read_semicolon() {
void IfcParse::IfcFile::register_inverse(unsigned id_from, const IfcParse::entity* from_entity, Token t, int attribute_index) { void IfcParse::IfcFile::register_inverse(unsigned id_from, const IfcParse::entity* from_entity, Token t, int attribute_index) {
// Assume a check on token type has already been performed // Assume a check on token type has already been performed
const auto* e = from_entity; const auto* e = from_entity;
byref_excl_[t.value_int].push_back(id_from); byref_excl_[{t.value_int, e->index_in_schema(), attribute_index}].push_back(id_from);
while (e != nullptr) {
byref_[{t.value_int, e->index_in_schema(), attribute_index}].push_back(id_from);
e = e->supertype();
}
} }
void IfcParse::IfcFile::register_inverse(unsigned id_from, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass* inst, int attribute_index) { void IfcParse::IfcFile::register_inverse(unsigned id_from, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass* inst, int attribute_index) {
const auto* e = from_entity; const auto* e = from_entity;
byref_excl_[inst->id()].push_back(id_from); byref_excl_[{inst->id(), e->index_in_schema(), attribute_index}].push_back(id_from);
while (e != nullptr) {
byref_[{inst->id(), e->index_in_schema(), attribute_index}].push_back(id_from);
e = e->supertype();
}
} }
void IfcParse::IfcFile::unregister_inverse(unsigned id_from, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass* inst, int attribute_index) { void IfcParse::IfcFile::unregister_inverse(unsigned id_from, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass* inst, int attribute_index) {
const auto* entity = from_entity; std::vector<int>& ids = byref_excl_[{inst->id(), from_entity->index_in_schema(), attribute_index}];
while (entity != nullptr) {
std::vector<int>& ids = byref_[{inst->id(), entity->index_in_schema(), attribute_index}];
std::vector<int>::iterator iter = std::find(ids.begin(), ids.end(), id_from);
if (iter == ids.end()) {
// @todo inverses also need to be populated when multiple instances are added to a new file.
// throw IfcParse::IfcException("Instance not found among inverses");
} else {
ids.erase(iter);
}
entity = entity->supertype();
}
std::vector<int>& ids = byref_excl_[inst->id()];
std::vector<int>::iterator iter = std::find(ids.begin(), ids.end(), id_from); std::vector<int>::iterator iter = std::find(ids.begin(), ids.end(), id_from);
if (iter == ids.end()) { if (iter == ids.end()) {
// @todo inverses also need to be populated when multiple instances are added to a new file. // @todo inverses also need to be populated when multiple instances are added to a new file.
@@ -917,7 +872,7 @@ namespace {
} }
void operator()(const IfcUtil::IfcBaseClass* const& i) { void operator()(const IfcUtil::IfcBaseClass* const& i) {
if (i->declaration().as_entity() == nullptr) { if (i->declaration().as_entity() == nullptr) {
i->data().toString(data_, true); i->toString(data_, upper_);
} else { } else {
data_ << "#" << i->id(); data_ << "#" << i->id();
} }
@@ -1025,20 +980,6 @@ namespace {
void IfcEntityInstanceData::toString(std::ostream& ss, bool upper, const entity* decl) const { void IfcEntityInstanceData::toString(std::ostream& ss, bool upper, const entity* decl) const {
ss.imbue(std::locale::classic()); ss.imbue(std::locale::classic());
/*
std::string dt;
if (type_ != nullptr) {
dt = type()->name();
if (upper) {
boost::to_upper(dt);
}
if ((type()->as_entity() != nullptr) || id_ != 0) {
ss << "#" << id_ << "=";
}
}
*/
ss << "("; ss << "(";
StringBuilderVisitor vis(ss, upper); StringBuilderVisitor vis(ss, upper);
@@ -1206,149 +1147,8 @@ void IfcUtil::IfcBaseClass::set_attribute_value(size_t i, const T& t) {
} }
data_.storage_.set(i, t); data_.storage_.set(i, t);
auto new_attribute = data_.get_attribute_value(i); auto new_attribute = data_.get_attribute_value(i);
/*
Argument* new_attribute = a;
if (make_copy) {
if (attr_type == IfcUtil::Argument_UNKNOWN) {
attr_type = a->type();
} else if (a->isNull()) {
attr_type = IfcUtil::Argument_NULL;
}
IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument();
switch (attr_type) {
case IfcUtil::Argument_NULL:
copy->set(boost::blank());
break;
case IfcUtil::Argument_DERIVED:
copy->set(IfcWrite::IfcWriteArgument::Derived());
break;
case IfcUtil::Argument_INT:
copy->set(static_cast<int>(*a));
break;
case IfcUtil::Argument_BOOL:
copy->set(static_cast<bool>(*a));
break;
case IfcUtil::Argument_LOGICAL: {
boost::logic::tribool tb = *a;
copy->set(tb);
break;
}
case IfcUtil::Argument_DOUBLE:
copy->set(static_cast<double>(*a));
break;
case IfcUtil::Argument_STRING:
copy->set(static_cast<std::string>(*a));
break;
case IfcUtil::Argument_BINARY: {
boost::dynamic_bitset<> attr_value = *a;
copy->set(attr_value);
break;
}
case IfcUtil::Argument_AGGREGATE_OF_INT: {
std::vector<int> attr_value = *a;
copy->set(attr_value);
break;
}
case IfcUtil::Argument_AGGREGATE_OF_DOUBLE: {
std::vector<double> attr_value = *a;
copy->set(attr_value);
break;
}
case IfcUtil::Argument_AGGREGATE_OF_STRING: {
std::vector<std::string> attr_value = *a;
copy->set(attr_value);
break;
}
case IfcUtil::Argument_AGGREGATE_OF_BINARY: {
std::vector<boost::dynamic_bitset<>> attr_value = *a;
copy->set(attr_value);
break;
}
case IfcUtil::Argument_ENUMERATION: {
std::string enum_literal = a->toString();
// Remove leading and trailing '.'
enum_literal = enum_literal.substr(1, enum_literal.size() - 2);
const IfcParse::enumeration_type* enum_type = type()->as_enumeration_type() != nullptr
? type()->as_enumeration_type()
: type()->as_entity()->attribute_by_index(i)->type_of_attribute()->as_named_type()->declared_type()->as_enumeration_type();
std::vector<std::string>::const_iterator it = std::find(
enum_type->enumeration_items().begin(),
enum_type->enumeration_items().end(),
enum_literal);
if (it == enum_type->enumeration_items().end()) {
throw IfcParse::IfcException(enum_literal + " does not name a valid item for " + enum_type->name());
}
copy->set(IfcWrite::IfcWriteArgument::EnumerationReference(it - enum_type->enumeration_items().begin(), it->c_str()));
break;
}
case IfcUtil::Argument_ENTITY_INSTANCE: {
copy->set(static_cast<IfcUtil::IfcBaseClass*>(*a));
break;
}
case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: {
aggregate_of_instance::ptr instances = *a;
aggregate_of_instance::ptr mapped_instances(new aggregate_of_instance);
// @todo mapped_instances are not actually mapped to the file using add().
for (aggregate_of_instance::it it = instances->begin(); it != instances->end(); ++it) {
mapped_instances->push(*it);
}
copy->set(mapped_instances);
break;
}
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT: {
std::vector<std::vector<int>> attr_value = *a;
copy->set(attr_value);
break;
}
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE: {
std::vector<std::vector<double>> attr_value = *a;
copy->set(attr_value);
break;
}
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE: {
aggregate_of_aggregate_of_instance::ptr instances = *a;
aggregate_of_aggregate_of_instance::ptr mapped_instances(new aggregate_of_aggregate_of_instance);
for (aggregate_of_aggregate_of_instance::outer_it it = instances->begin(); it != instances->end(); ++it) {
std::vector<IfcUtil::IfcBaseClass*> inner;
for (aggregate_of_aggregate_of_instance::inner_it jt = it->begin(); jt != it->end(); ++jt) {
inner.push_back(*jt);
}
mapped_instances->push(inner);
}
copy->set(mapped_instances);
break;
}
case IfcUtil::Argument_EMPTY_AGGREGATE:
case IfcUtil::Argument_AGGREGATE_OF_EMPTY_AGGREGATE: {
IfcUtil::ArgumentType t2 = IfcUtil::from_parameter_type(type()->as_entity()->attribute_by_index(i)->type_of_attribute());
delete copy;
copy = 0;
setArgument(i, a, t2, make_copy);
break;
}
default:
case IfcUtil::Argument_UNKNOWN:
throw IfcParse::IfcException(std::string("Unknown attribute encountered: '") + a->toString() + "' at index '" + boost::lexical_cast<std::string>(i) + "'");
break;
}
if (copy == nullptr) {
return;
}
new_attribute = copy;
}
*/
if (file_ != nullptr) { if (file_ != nullptr) {
// Register inverse indices in file // Register inverse indices in file
register_inverse_visitor visitor(*file_, this); register_inverse_visitor visitor(*file_, this);
@@ -1385,16 +1185,19 @@ IfcFile::IfcFile(const std::string& fn, bool mmap) {
} }
#else #else
IfcFile::IfcFile(const std::string& path) { IfcFile::IfcFile(const std::string& path) {
initialize_(new IfcSpfStream(path)); IfcSpfStream s(path);
initialize_(&s);
} }
#endif #endif
IfcFile::IfcFile(std::istream& stream, int length) { IfcFile::IfcFile(std::istream& stream, int length) {
initialize_(new IfcSpfStream(stream, length)); IfcSpfStream s(stream, length);
initialize_(&s);
} }
IfcFile::IfcFile(void* data, int length) { IfcFile::IfcFile(void* data, int length) {
initialize_(new IfcSpfStream(data, length)); IfcSpfStream s(data, length);
initialize_(&s);
} }
IfcFile::IfcFile(IfcParse::IfcSpfStream* s) { IfcFile::IfcFile(IfcParse::IfcSpfStream* s) {
@@ -1493,7 +1296,7 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
parse_context ps; parse_context ps;
load(current_id, entity_type->as_entity(), ps, -1); load(current_id, entity_type->as_entity(), ps, -1);
instance = schema_->instantiate(entity_type->name(), ps.construct(current_id, references_to_resolve, entity_type)); instance = schema_->instantiate(entity_type, ps.construct(current_id, references_to_resolve, entity_type));
instance->file_ = this; instance->file_ = this;
instance->id_ = current_id; instance->id_ = current_id;
@@ -1525,27 +1328,10 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
const IfcParse::declaration* ty = &instance->declaration(); const IfcParse::declaration* ty = &instance->declaration();
{ {
aggregate_of_instance::ptr insts = instances_by_type_excl_subtypes(ty); if (bytype_excl_.find(ty) == bytype_excl_.end()) {
if (!insts) { bytype_excl_[ty].reset(new aggregate_of_instance());
insts = aggregate_of_instance::ptr(new aggregate_of_instance());
bytype_excl_[ty] = insts;
}
insts->push(instance);
}
for (;;) {
aggregate_of_instance::ptr insts = instances_by_type(ty);
if (!insts) {
insts = aggregate_of_instance::ptr(new aggregate_of_instance());
bytype_[ty] = insts;
}
insts->push(instance);
const IfcParse::declaration* pt = ty->as_entity()->supertype();
if (pt != nullptr) {
ty = pt;
} else {
break;
} }
bytype_excl_[ty]->push(instance);
} }
if (byid_.find(current_id) != byid_.end()) { if (byid_.find(current_id) != byid_.end()) {
@@ -1588,6 +1374,8 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
Logger::Status("\rDone scanning file "); Logger::Status("\rDone scanning file ");
delete tokens;
for (auto& p : references_to_resolve) { for (auto& p : references_to_resolve) {
boost::apply_visitor([this, &p](auto& v) { boost::apply_visitor([this, &p](auto& v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, reference_or_simple_type>) { if constexpr (std::is_same_v<std::decay_t<decltype(v)>, reference_or_simple_type>) {
@@ -1602,6 +1390,7 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
}, v)); }, v));
} else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<reference_or_simple_type>>) { } else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<reference_or_simple_type>>) {
aggregate_of_instance::ptr instances(new aggregate_of_instance); aggregate_of_instance::ptr instances(new aggregate_of_instance);
instances->reserve(v.size());
for (auto& p : v) { for (auto& p : v) {
instances->push(boost::apply_visitor([this](auto inst) { instances->push(boost::apply_visitor([this](auto inst) {
IfcUtil::IfcBaseClass* ptr; IfcUtil::IfcBaseClass* ptr;
@@ -1810,7 +1599,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
IfcFile* other_file = entity->file_; IfcFile* other_file = entity->file_;
IfcEntityInstanceData we(entity->data()); IfcEntityInstanceData we(entity->data());
new_entity = schema()->instantiate(entity->declaration().name(), std::move(we)); new_entity = schema()->instantiate(&entity->declaration(), std::move(we));
// In case an entity is added that contains geometry, the unit // In case an entity is added that contains geometry, the unit
// information needs to be accounted for for IfcLengthMeasures. // information needs to be accounted for for IfcLengthMeasures.
@@ -1931,7 +1720,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
Logger::Message(Logger::LOG_WARNING, ss.str()); Logger::Message(Logger::LOG_WARNING, ss.str());
} }
byguid_[guid] = new_entity; byguid_[guid] = new_entity;
} catch (const IfcException& ex) { } catch (const std::exception& ex) {
Logger::Message(Logger::LOG_ERROR, ex.what()); Logger::Message(Logger::LOG_ERROR, ex.what());
} }
} }
@@ -1940,28 +1729,10 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
const IfcParse::declaration* ty = &new_entity->declaration(); const IfcParse::declaration* ty = &new_entity->declaration();
if (ty->as_entity() != nullptr) { if (ty->as_entity() != nullptr) {
aggregate_of_instance::ptr insts = instances_by_type_excl_subtypes(ty); if (bytype_excl_.find(ty) == bytype_excl_.end()) {
if (!insts) { bytype_excl_[ty].reset(new aggregate_of_instance());
insts = aggregate_of_instance::ptr(new aggregate_of_instance());
bytype_excl_[ty] = insts;
}
insts->push(new_entity);
}
for (; ty->as_entity() != nullptr;) {
aggregate_of_instance::ptr insts = instances_by_type(ty);
if (!insts) {
insts = aggregate_of_instance::ptr(new aggregate_of_instance());
bytype_[ty] = insts;
}
insts->push(new_entity);
const IfcParse::declaration* pt = ty->as_entity()->supertype();
if (pt != nullptr) {
ty = pt;
} else {
break;
} }
bytype_excl_[ty]->push(new_entity);
} }
if (ty->as_entity() != nullptr) { if (ty->as_entity() != nullptr) {
@@ -2106,11 +1877,11 @@ void IfcFile::process_deletion_() {
} }
if (!batch_mode_) { if (!batch_mode_) {
byref_.erase( byref_excl_.erase(
byref_.lower_bound({id, -1, -1}), byref_excl_.lower_bound({id, -1, -1}),
byref_.upper_bound({id, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()})); byref_excl_.upper_bound({id, std::numeric_limits<short>::max(), std::numeric_limits<short>::max()}));
byref_excl_.erase(id); // byref_excl_.erase(id);
// This is based on traversal which needs instances to still be contained in the map. // This is based on traversal which needs instances to still be contained in the map.
// another option would be to keep byid intact for the remainder of this loop // another option would be to keep byid intact for the remainder of this loop
@@ -2124,21 +1895,14 @@ void IfcFile::process_deletion_() {
// Do not update inverses for simple types (which have id()==0 in IfcOpenShell). // Do not update inverses for simple types (which have id()==0 in IfcOpenShell).
if (name != 0) { if (name != 0) {
{ {
auto lower = byref_.lower_bound({name, -1, -1}); auto lower = byref_excl_.lower_bound({name, -1, -1});
auto upper = byref_.upper_bound({name, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()}); auto upper = byref_excl_.upper_bound({name, std::numeric_limits<short>::max(), std::numeric_limits<short>::max()});
for (auto byref_it = lower; byref_it != upper; ++byref_it) { for (auto byref_it = lower; byref_it != upper; ++byref_it) {
auto& ids = byref_it->second; auto& ids = byref_it->second;
ids.erase(std::remove(ids.begin(), ids.end(), id), ids.end()); ids.erase(std::remove(ids.begin(), ids.end(), id), ids.end());
} }
} }
{
auto byref_it = byref_excl_.find(name);
if (byref_it != byref_excl_.end()) {
auto& ids = byref_it->second;
ids.erase(std::remove(ids.begin(), ids.end(), id), ids.end());
}
}
} }
} }
} }
@@ -2158,28 +1922,13 @@ void IfcFile::process_deletion_() {
const IfcParse::declaration* ty = &entity->declaration(); const IfcParse::declaration* ty = &entity->declaration();
{ {
aggregate_of_instance::ptr instances_of_same_type = instances_by_type_excl_subtypes(ty); auto it = bytype_excl_.find(ty);
instances_of_same_type->remove(entity); if (it != bytype_excl_.end()) {
if (instances_of_same_type->size() == 0) { it->second->remove(entity);
if (it->second->size() == 0) {
bytype_excl_.erase(ty); bytype_excl_.erase(ty);
} }
} }
for (;;) {
aggregate_of_instance::ptr instances_of_same_type = instances_by_type(ty);
if (instances_of_same_type) {
instances_of_same_type->remove(entity);
}
if (instances_of_same_type->size() == 0) {
bytype_.erase(ty);
}
const IfcParse::declaration* pt = ty->as_entity()->supertype();
if (pt != nullptr) {
ty = pt;
} else {
break;
}
} }
// entity_file_map is in place to prevent duplicate definitions with usage of add(). // entity_file_map is in place to prevent duplicate definitions with usage of add().
@@ -2196,24 +1945,8 @@ void IfcFile::process_deletion_() {
} }
if (batch_mode_) { if (batch_mode_) {
for (auto it = byref_.begin(); it != byref_.end();) {
bool do_delete = batch_deletion_ids_.get<1>().find(std::get<INSTANCE_ID>(it->first)) != batch_deletion_ids_.get<1>().end();
if (!do_delete) {
it->second.erase(std::remove_if(it->second.begin(), it->second.end(), [this](int x) {
return batch_deletion_ids_.get<1>().find(x) != batch_deletion_ids_.get<1>().end();
}),
it->second.end());
do_delete = it->second.empty();
}
if (do_delete) {
it = byref_.erase(it);
} else {
++it;
}
}
for (auto it = byref_excl_.begin(); it != byref_excl_.end();) { for (auto it = byref_excl_.begin(); it != byref_excl_.end();) {
bool do_delete = batch_deletion_ids_.get<1>().find(it->first) != batch_deletion_ids_.get<1>().end(); bool do_delete = batch_deletion_ids_.get<1>().find(std::get<INSTANCE_ID>(it->first)) != batch_deletion_ids_.get<1>().end();
if (!do_delete) { if (!do_delete) {
it->second.erase(std::remove_if(it->second.begin(), it->second.end(), [this](int x) { it->second.erase(std::remove_if(it->second.begin(), it->second.end(), [this](int x) {
return batch_deletion_ids_.get<1>().find(x) != batch_deletion_ids_.get<1>().end(); return batch_deletion_ids_.get<1>().find(x) != batch_deletion_ids_.get<1>().end();
@@ -2232,14 +1965,40 @@ void IfcFile::process_deletion_() {
batch_deletion_ids_.clear(); batch_deletion_ids_.clear();
} }
namespace {
template <typename Fn>
void visit_subtypes(const IfcParse::entity* ent, Fn fn) {
fn(ent);
for (auto& st : ent->subtypes()) {
visit_subtypes(st, fn);
}
}
template <typename Fn>
void visit_supertypes(const IfcParse::entity* ent, Fn fn) {
fn(ent);
if (ent->supertype()) {
visit_supertypes(ent->supertype(), fn);
}
}
}
aggregate_of_instance::ptr IfcFile::instances_by_type(const IfcParse::declaration* t) { aggregate_of_instance::ptr IfcFile::instances_by_type(const IfcParse::declaration* t) {
entities_by_type_t::const_iterator it = bytype_.find(t); aggregate_of_instance::ptr insts(new aggregate_of_instance);
return (it == bytype_.end()) ? aggregate_of_instance::ptr() : it->second; if (t->as_entity()) {
visit_subtypes(t->as_entity(), [this, &insts](const IfcParse::entity* ent) {
auto it = bytype_excl_.find(ent);
if (it != bytype_excl_.end()) {
insts->push(it->second);
}
});
}
return insts;
} }
aggregate_of_instance::ptr IfcFile::instances_by_type_excl_subtypes(const IfcParse::declaration* t) { aggregate_of_instance::ptr IfcFile::instances_by_type_excl_subtypes(const IfcParse::declaration* t) {
entities_by_type_t::const_iterator it = bytype_excl_.find(t); entities_by_type_t::const_iterator it = bytype_excl_.find(t);
return (it == bytype_excl_.end()) ? aggregate_of_instance::ptr() : it->second; return (it == bytype_excl_.end()) ? aggregate_of_instance::ptr(new aggregate_of_instance) : it->second;
} }
aggregate_of_instance::ptr IfcFile::instances_by_type(const std::string& t) { aggregate_of_instance::ptr IfcFile::instances_by_type(const std::string& t) {
@@ -2251,10 +2010,14 @@ aggregate_of_instance::ptr IfcFile::instances_by_type_excl_subtypes(const std::s
} }
aggregate_of_instance::ptr IfcFile::instances_by_reference(int t) { aggregate_of_instance::ptr IfcFile::instances_by_reference(int t) {
auto lower = byref_excl_.lower_bound({ t, -1, -1 });
auto upper = byref_excl_.upper_bound({ t, std::numeric_limits<short>::max(), std::numeric_limits<short>::max() });
aggregate_of_instance::ptr ret(new aggregate_of_instance); aggregate_of_instance::ptr ret(new aggregate_of_instance);
for (auto& i : byref_excl_[t]) { for (auto it = lower; it != upper; ++it) {
for (auto& i : it->second) {
ret->push(instance_by_id(i)); ret->push(instance_by_id(i));
} }
}
return ret; return ret;
} }
@@ -2286,8 +2049,6 @@ IfcFile::~IfcFile() {
for (auto* entity : entities_to_delete) { for (auto* entity : entities_to_delete) {
delete entity; delete entity;
} }
delete stream;
delete tokens;
} }
IfcFile::entity_by_id_t::const_iterator IfcFile::begin() const { IfcFile::entity_by_id_t::const_iterator IfcFile::begin() const {
@@ -2306,14 +2067,6 @@ IfcFile::type_iterator IfcFile::types_end() const {
return bytype_excl_.end(); return bytype_excl_.end();
} }
IfcFile::type_iterator IfcFile::types_incl_super_begin() const {
return bytype_.begin();
}
IfcFile::type_iterator IfcFile::types_incl_super_end() const {
return bytype_.end();
}
namespace { namespace {
struct id_instance_pair_sorter { struct id_instance_pair_sorter {
bool operator()(const IfcParse::IfcFile::entity_by_id_t::value_type& a, const IfcParse::IfcFile::entity_by_id_t::value_type& b) const { bool operator()(const IfcParse::IfcFile::entity_by_id_t::value_type& a, const IfcParse::IfcFile::entity_by_id_t::value_type& b) const {
@@ -2362,8 +2115,8 @@ std::string IfcFile::createTimestamp() const {
std::vector<int> IfcFile::get_inverse_indices(int instance_id) { std::vector<int> IfcFile::get_inverse_indices(int instance_id) {
std::vector<int> return_value; std::vector<int> return_value;
auto lower = byref_.lower_bound({instance_id, -1, -1}); auto lower = byref_excl_.lower_bound({instance_id, -1, -1});
auto upper = byref_.upper_bound({instance_id, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()}); auto upper = byref_excl_.upper_bound({instance_id, std::numeric_limits<short>::max(), std::numeric_limits<short>::max()});
// Mapping of instance id to attribute offset. // Mapping of instance id to attribute offset.
std::map<int, std::vector<int>> mapping; std::map<int, std::vector<int>> mapping;
@@ -2401,19 +2154,16 @@ std::vector<int> IfcFile::get_inverse_indices(int instance_id) {
} }
aggregate_of_instance::ptr IfcFile::getInverse(int instance_id, const IfcParse::declaration* type, int attribute_index) { aggregate_of_instance::ptr IfcFile::getInverse(int instance_id, const IfcParse::declaration* type, int attribute_index) {
// @todo is this mutex still necessary?
static std::mutex mtx;
std::lock_guard<std::mutex> lock(mtx);
if (type == nullptr && attribute_index == -1) { if (type == nullptr && attribute_index == -1) {
return instances_by_reference(instance_id); return instances_by_reference(instance_id);
} }
aggregate_of_instance::ptr return_value(new aggregate_of_instance); aggregate_of_instance::ptr return_value(new aggregate_of_instance);
visit_subtypes(type->as_entity(), [this, attribute_index, instance_id, &return_value](const IfcParse::declaration* ent) {
if (attribute_index == -1) { if (attribute_index == -1) {
auto lower = byref_.lower_bound({instance_id, type->index_in_schema(), -1}); auto lower = byref_excl_.lower_bound({ instance_id, ent->index_in_schema(), -1 });
auto upper = byref_.upper_bound({instance_id, type->index_in_schema(), std::numeric_limits<int>::max()}); auto upper = byref_excl_.upper_bound({ instance_id, ent->index_in_schema(), std::numeric_limits<short>::max() });
for (auto it = lower; it != upper; ++it) { for (auto it = lower; it != upper; ++it) {
for (auto& i : it->second) { for (auto& i : it->second) {
@@ -2421,19 +2171,26 @@ aggregate_of_instance::ptr IfcFile::getInverse(int instance_id, const IfcParse::
} }
} }
} else { } else {
auto it = byref_.find({instance_id, type->index_in_schema(), attribute_index}); auto it = byref_excl_.find({ instance_id, ent->index_in_schema(), attribute_index });
if (it != byref_.end()) { if (it != byref_excl_.end()) {
for (auto& i : it->second) { for (auto& i : it->second) {
return_value->push(instance_by_id(i)); return_value->push(instance_by_id(i));
} }
} }
} }
});
return return_value; return return_value;
} }
size_t IfcFile::getTotalInverses(int instance_id) { size_t IfcFile::getTotalInverses(int instance_id) {
return byref_excl_[instance_id].size(); size_t n = 0;
auto lower = byref_excl_.lower_bound({ instance_id, -1, -1 });
auto upper = byref_excl_.upper_bound({ instance_id, std::numeric_limits<short>::max(), std::numeric_limits<short>::max() });
for (auto it = lower; it != upper; ++it) {
n += it->second.size();
}
return n;
} }
void IfcFile::setDefaultHeaderValues() { void IfcFile::setDefaultHeaderValues() {
@@ -2531,11 +2288,7 @@ void IfcParse::IfcFile::build_inverses_(IfcUtil::IfcBaseClass* inst) {
if (attr->declaration().as_entity() != nullptr) { if (attr->declaration().as_entity() != nullptr) {
unsigned entity_attribute_id = attr->id(); unsigned entity_attribute_id = attr->id();
const auto* decl = inst->declaration().as_entity(); const auto* decl = inst->declaration().as_entity();
byref_excl_[entity_attribute_id].push_back(inst->id()); byref_excl_[{entity_attribute_id, decl->index_in_schema(), idx}].push_back(inst->id());
while (decl != nullptr) {
byref_[{entity_attribute_id, decl->index_in_schema(), idx}].push_back(inst->id());
decl = decl->supertype();
}
} }
}; };
@@ -2552,15 +2305,6 @@ std::atomic_uint32_t IfcUtil::IfcBaseClass::counter_(0);
bool IfcParse::IfcFile::guid_map_ = true; bool IfcParse::IfcFile::guid_map_ = true;
/*
template <typename T>
void IfcUtil::IfcBaseClass::set_value(int index, const T& value) {
IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();
attr->set(value);
data_->setArgument(index, attr);
}
*/
void IfcUtil::IfcBaseClass::unset_attribute_value(size_t index) { void IfcUtil::IfcBaseClass::unset_attribute_value(size_t index) {
data_.storage_.set(index, Blank{}); data_.storage_.set(index, Blank{});
} }
@@ -2571,7 +2315,11 @@ void IfcUtil::IfcBaseClass::toString(std::ostream& out, bool upper) const
if (ent) { if (ent) {
out << "#" << as<IfcUtil::IfcBaseEntity>()->id() << "="; out << "#" << as<IfcUtil::IfcBaseEntity>()->id() << "=";
} }
if (upper) {
out << declaration().name_uc(); out << declaration().name_uc();
} else {
out << declaration().name();
}
data().toString(out, upper, ent); data().toString(out, upper, ent);
} }
+3 -3
View File
@@ -152,11 +152,11 @@ IfcParse::schema_definition::~schema_definition() {
delete factory_; delete factory_;
} }
IfcUtil::IfcBaseClass* IfcParse::schema_definition::instantiate(const std::string& type_name, IfcEntityInstanceData&& data) const { IfcUtil::IfcBaseClass* IfcParse::schema_definition::instantiate(const IfcParse::declaration* decl, IfcEntityInstanceData&& data) const {
if (factory_ != nullptr) { if (factory_ != nullptr) {
return (*factory_)(declaration_by_name(type_name), std::move(data)); return (*factory_)(decl, std::move(data));
} }
return new IfcUtil::IfcLateBoundEntity(declaration_by_name(type_name), std::move(data)); return new IfcUtil::IfcLateBoundEntity(decl, std::move(data));
} }
void IfcParse::register_schema(schema_definition* schema) { void IfcParse::register_schema(schema_definition* schema) {
+1 -1
View File
@@ -507,7 +507,7 @@ class IFC_PARSE_API schema_definition {
const std::string& name() const { return name_; } const std::string& name() const { return name_; }
IfcUtil::IfcBaseClass* instantiate(const std::string& type_name, IfcEntityInstanceData&& data) const; IfcUtil::IfcBaseClass* instantiate(const IfcParse::declaration* decl, IfcEntityInstanceData&& data) const;
}; };
IFC_PARSE_API const schema_definition* schema_by_name(const std::string&); IFC_PARSE_API const schema_definition* schema_by_name(const std::string&);
+1 -1
View File
@@ -503,7 +503,7 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
} }
} }
IfcUtil::IfcBaseClass* newinst = state->file->schema()->instantiate(decl->name(), std::move(untyped)); IfcUtil::IfcBaseClass* newinst = state->file->schema()->instantiate(decl, std::move(untyped));
if (state->dialect == ifcxml_dialect_ifc4) { if (state->dialect == ifcxml_dialect_ifc4) {
// In IFC2X3 not added directly because attrs such as GlobalId are in // In IFC2X3 not added directly because attrs such as GlobalId are in
+26 -1
View File
@@ -34,6 +34,8 @@ variant - which is the maximum size of its constituents - is reduced.
#include <memory> #include <memory>
#include <tuple> #include <tuple>
#include "IfcException.h"
namespace impl { namespace impl {
// Trait to detect unique_ptr // Trait to detect unique_ptr
template <typename...> struct is_unique_ptr : std::false_type {}; template <typename...> struct is_unique_ptr : std::false_type {};
@@ -216,7 +218,13 @@ public:
template<typename T> template<typename T>
const T& get(std::size_t index) const { const T& get(std::size_t index) const {
if (size_and_indices_[index + 1] != impl::TypeIndex<T, Types...>::value) { if (size_and_indices_[index + 1] != impl::TypeIndex<T, Types...>::value) {
throw std::bad_cast(); // @todo this IfcException is silly. Figure out what
// to do, but at the moment it is specifically caught
// in various places.
throw IfcParse::IfcException(
"Type held at index " + std::to_string(index) + " is " +
get_type_name(index) + " and not " + typeid(T).name()
);
} }
using V = typename std::tuple_element<impl::TypeIndex_v<T, Types...>, impl::MapTypes_t<Types... >>::type; using V = typename std::tuple_element<impl::TypeIndex_v<T, Types...>, impl::MapTypes_t<Types... >>::type;
if constexpr (impl::is_unique_ptr<V>::value) { if constexpr (impl::is_unique_ptr<V>::value) {
@@ -290,6 +298,23 @@ private:
return decltype(std::declval<Visitor>()(std::declval<typename std::tuple_element_t<0, impl::MapTypes_t<Types...>> &>())){}; return decltype(std::declval<Visitor>()(std::declval<typename std::tuple_element_t<0, impl::MapTypes_t<Types...>> &>())){};
} }
} }
template <size_t I>
const char* get_type_name_impl(size_t i) const {
if constexpr (I == 0) {
return "";
} else {
if (i == I - 1) {
return typeid(std::tuple_element_t<I - 1, std::tuple<Types...>>).name();
} else {
return get_type_name_impl<I - 1>(i);
}
}
}
const char* get_type_name(size_t i) const {
return get_type_name_impl<sizeof...(Types)>(i);
}
}; };
#endif #endif
+21 -19
View File
@@ -186,6 +186,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
return ts; return ts;
} }
/*
std::vector<std::string> types_with_super() const { std::vector<std::string> types_with_super() const {
const size_t n = std::distance($self->types_incl_super_begin(), $self->types_incl_super_end()); const size_t n = std::distance($self->types_incl_super_begin(), $self->types_incl_super_end());
std::vector<std::string> ts; std::vector<std::string> ts;
@@ -193,6 +194,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
std::transform($self->types_incl_super_begin(), $self->types_incl_super_end(), std::back_inserter(ts), helper_fn_declaration_get_name); std::transform($self->types_incl_super_begin(), $self->types_incl_super_end(), std::back_inserter(ts), helper_fn_declaration_get_name);
return ts; return ts;
} }
*/
std::string schema_name() const { std::string schema_name() const {
if ($self->schema() == 0) return ""; if ($self->schema() == 0) return "";
@@ -368,7 +370,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsNull(unsigned int i) { void setArgumentAsNull(unsigned int i) {
bool is_optional = $self->declaration().as_entity()->attribute_by_index(i)->optional(); bool is_optional = $self->declaration().as_entity()->attribute_by_index(i)->optional();
if (is_optional) { if (is_optional) {
self->data().storage_.set(i, Blank{}); self->set_attribute_value(i, Blank{});
} else { } else {
throw IfcParse::IfcException("Attribute not set"); throw IfcParse::IfcException("Attribute not set");
} }
@@ -377,9 +379,9 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsInt(unsigned int i, int v) { void setArgumentAsInt(unsigned int i, int v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_INT) { if (arg_type == IfcUtil::Argument_INT) {
self->data().storage_.set(i, v); self->set_attribute_value(i, v);
} else if ( (arg_type == IfcUtil::Argument_BOOL) && ( (v == 0) || (v == 1) ) ) { } else if ( (arg_type == IfcUtil::Argument_BOOL) && ( (v == 0) || (v == 1) ) ) {
self->data().storage_.set(i, v); self->set_attribute_value(i, v);
} else { } else {
throw IfcParse::IfcException("Attribute not set"); throw IfcParse::IfcException("Attribute not set");
} }
@@ -388,7 +390,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsBool(unsigned int i, bool v) { void setArgumentAsBool(unsigned int i, bool v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_BOOL) { if (arg_type == IfcUtil::Argument_BOOL) {
self->data().storage_.set(i, v); self->set_attribute_value(i, v);
} else { } else {
throw IfcParse::IfcException("Attribute not set"); throw IfcParse::IfcException("Attribute not set");
} }
@@ -397,7 +399,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsLogical(unsigned int i, boost::logic::tribool v) { void setArgumentAsLogical(unsigned int i, boost::logic::tribool v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_LOGICAL) { if (arg_type == IfcUtil::Argument_LOGICAL) {
self->data().storage_.set(i, v); self->set_attribute_value(i, v);
} else { } else {
throw IfcParse::IfcException("Attribute not set"); throw IfcParse::IfcException("Attribute not set");
} }
@@ -406,7 +408,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsDouble(unsigned int i, double v) { void setArgumentAsDouble(unsigned int i, double v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_DOUBLE) { if (arg_type == IfcUtil::Argument_DOUBLE) {
self->data().storage_.set(i, v); self->set_attribute_value(i, v);
} else { } else {
throw IfcParse::IfcException("Attribute not set"); throw IfcParse::IfcException("Attribute not set");
} }
@@ -415,15 +417,15 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsString(unsigned int i, const std::string& a) { void setArgumentAsString(unsigned int i, const std::string& a) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_STRING) { if (arg_type == IfcUtil::Argument_STRING) {
self->data().storage_.set(i, a); self->set_attribute_value(i, a);
} else if (arg_type == IfcUtil::Argument_ENUMERATION) { } else if (arg_type == IfcUtil::Argument_ENUMERATION) {
const IfcParse::enumeration_type* enum_type = $self->declaration().schema()->declaration_by_name($self->declaration().type())->as_entity()-> const IfcParse::enumeration_type* enum_type = $self->declaration().schema()->declaration_by_name($self->declaration().type())->as_entity()->
attribute_by_index(i)->type_of_attribute()->as_named_type()->declared_type()->as_enumeration_type(); attribute_by_index(i)->type_of_attribute()->as_named_type()->declared_type()->as_enumeration_type();
self->data().storage_.set(i, EnumerationReference(enum_type, enum_type->lookup_enum_offset(a))); self->set_attribute_value(i, EnumerationReference(enum_type, enum_type->lookup_enum_offset(a)));
} else if (arg_type == IfcUtil::Argument_BINARY) { } else if (arg_type == IfcUtil::Argument_BINARY) {
if (IfcUtil::valid_binary_string(a)) { if (IfcUtil::valid_binary_string(a)) {
boost::dynamic_bitset<> bits(a); boost::dynamic_bitset<> bits(a);
self->data().storage_.set(i, bits); self->set_attribute_value(i, bits);
} else { } else {
throw IfcParse::IfcException("String not a valid binary representation"); throw IfcParse::IfcException("String not a valid binary representation");
} }
@@ -435,7 +437,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsAggregateOfInt(unsigned int i, const std::vector<int>& v) { void setArgumentAsAggregateOfInt(unsigned int i, const std::vector<int>& v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_INT) { if (arg_type == IfcUtil::Argument_AGGREGATE_OF_INT) {
self->data().storage_.set(i, v); self->set_attribute_value(i, v);
} else { } else {
throw IfcParse::IfcException("Attribute not set"); throw IfcParse::IfcException("Attribute not set");
} }
@@ -444,7 +446,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsAggregateOfDouble(unsigned int i, const std::vector<double>& v) { void setArgumentAsAggregateOfDouble(unsigned int i, const std::vector<double>& v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) { if (arg_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) {
self->data().storage_.set(i, v); self->set_attribute_value(i, v);
} else { } else {
throw IfcParse::IfcException("Attribute not set"); throw IfcParse::IfcException("Attribute not set");
} }
@@ -453,7 +455,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsAggregateOfString(unsigned int i, const std::vector<std::string>& v) { void setArgumentAsAggregateOfString(unsigned int i, const std::vector<std::string>& v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_STRING) { if (arg_type == IfcUtil::Argument_AGGREGATE_OF_STRING) {
self->data().storage_.set(i, v); self->set_attribute_value(i, v);
} else if (arg_type == IfcUtil::Argument_AGGREGATE_OF_BINARY) { } else if (arg_type == IfcUtil::Argument_AGGREGATE_OF_BINARY) {
std::vector< boost::dynamic_bitset<> > bits; std::vector< boost::dynamic_bitset<> > bits;
bits.reserve(v.size()); bits.reserve(v.size());
@@ -464,7 +466,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
throw IfcParse::IfcException("String not a valid binary representation"); throw IfcParse::IfcException("String not a valid binary representation");
} }
} }
self->data().storage_.set(i, bits); self->set_attribute_value(i, bits);
} else { } else {
throw IfcParse::IfcException("Attribute not set"); throw IfcParse::IfcException("Attribute not set");
} }
@@ -473,7 +475,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsEntityInstance(unsigned int i, IfcUtil::IfcBaseClass* v) { void setArgumentAsEntityInstance(unsigned int i, IfcUtil::IfcBaseClass* v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_ENTITY_INSTANCE) { if (arg_type == IfcUtil::Argument_ENTITY_INSTANCE) {
self->data().storage_.set(i, v); self->set_attribute_value(i, v);
} else { } else {
throw IfcParse::IfcException("Attribute not set"); throw IfcParse::IfcException("Attribute not set");
} }
@@ -482,7 +484,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsAggregateOfEntityInstance(unsigned int i, aggregate_of_instance::ptr v) { void setArgumentAsAggregateOfEntityInstance(unsigned int i, aggregate_of_instance::ptr v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) { if (arg_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
self->data().storage_.set(i, v); self->set_attribute_value(i, v);
} else { } else {
throw IfcParse::IfcException("Attribute not set"); throw IfcParse::IfcException("Attribute not set");
} }
@@ -491,7 +493,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsAggregateOfAggregateOfInt(unsigned int i, const std::vector< std::vector<int> >& v) { void setArgumentAsAggregateOfAggregateOfInt(unsigned int i, const std::vector< std::vector<int> >& v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT) { if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT) {
self->data().storage_.set(i, v); self->set_attribute_value(i, v);
} else { } else {
throw IfcParse::IfcException("Attribute not set"); throw IfcParse::IfcException("Attribute not set");
} }
@@ -500,7 +502,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsAggregateOfAggregateOfDouble(unsigned int i, const std::vector< std::vector<double> >& v) { void setArgumentAsAggregateOfAggregateOfDouble(unsigned int i, const std::vector< std::vector<double> >& v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE) { if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE) {
self->data().storage_.set(i, v); self->set_attribute_value(i, v);
} else { } else {
throw IfcParse::IfcException("Attribute not set"); throw IfcParse::IfcException("Attribute not set");
} }
@@ -509,7 +511,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
void setArgumentAsAggregateOfAggregateOfEntityInstance(unsigned int i, aggregate_of_aggregate_of_instance::ptr v) { void setArgumentAsAggregateOfAggregateOfEntityInstance(unsigned int i, aggregate_of_aggregate_of_instance::ptr v) {
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) { if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) {
self->data().storage_.set(i, v); self->set_attribute_value(i, v);
} else { } else {
throw IfcParse::IfcException("Attribute not set"); throw IfcParse::IfcException("Attribute not set");
} }
@@ -590,7 +592,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
const IfcParse::schema_definition* schema = IfcParse::schema_by_name(schema_identifier); const IfcParse::schema_definition* schema = IfcParse::schema_by_name(schema_identifier);
const IfcParse::declaration* decl = schema->declaration_by_name(name); const IfcParse::declaration* decl = schema->declaration_by_name(name);
IfcEntityInstanceData data(storage_t(decl->as_entity() ? decl->as_entity()->attribute_count() : 1)); IfcEntityInstanceData data(storage_t(decl->as_entity() ? decl->as_entity()->attribute_count() : 1));
return schema->instantiate(decl->name(), std::move(data)); return schema->instantiate(decl, std::move(data));
} }
%} %}
+3 -2
View File
@@ -64,10 +64,8 @@ assert "Version" in dir(app)
g = ifcopenshell.file(schema=f.schema) g = ifcopenshell.file(schema=f.schema)
p = g.createIfcCartesianPoint((0.,0.)) p = g.createIfcCartesianPoint((0.,0.))
assert len(g.types()) == 1 assert len(g.types()) == 1
assert "IfcPoint" in g.types_with_super()
g.remove(p) g.remove(p)
assert len(g.types()) == 0 assert len(g.types()) == 0
assert len(g.types_with_super()) == 0
# Some operations on ifcopenshell.entity_instance # Some operations on ifcopenshell.entity_instance
assert f[22].Id == '' assert f[22].Id == ''
@@ -92,6 +90,9 @@ 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
# reopen, because we messed with the units
f = ifcopenshell.open("input/acad2010_walls.ifc")
# Test the BVH tree # Test the BVH tree
tree_settings = ifcopenshell.geom.settings() tree_settings = ifcopenshell.geom.settings()
tree_settings.set(tree_settings.DISABLE_OPENING_SUBTRACTIONS, True) tree_settings.set(tree_settings.DISABLE_OPENING_SUBTRACTIONS, True)