mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-28 03:05:33 +00:00
WIP
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -55,6 +55,8 @@
|
|||||||
* *
|
* *
|
||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
|
|
||||||
|
#define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR
|
||||||
|
|
||||||
#ifndef IFCGEOMITERATOR_H
|
#ifndef IFCGEOMITERATOR_H
|
||||||
#define IFCGEOMITERATOR_H
|
#define IFCGEOMITERATOR_H
|
||||||
|
|
||||||
|
|||||||
@@ -86,20 +86,17 @@ 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_;
|
||||||
|
|
||||||
|
uint32_t identity_;
|
||||||
|
public:
|
||||||
|
uint32_t id_;
|
||||||
|
IfcParse::IfcFile* file_;
|
||||||
|
protected:
|
||||||
IfcEntityInstanceData data_;
|
IfcEntityInstanceData data_;
|
||||||
|
|
||||||
static bool is_null(const IfcBaseClass* not_this) {
|
public:
|
||||||
return not_this == nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
uint32_t id_;
|
|
||||||
IfcParse::IfcFile* file_;
|
|
||||||
|
|
||||||
IfcBaseClass(IfcEntityInstanceData&& data)
|
IfcBaseClass(IfcEntityInstanceData&& data)
|
||||||
: identity_(counter_++)
|
: identity_(counter_++)
|
||||||
, data_(std::move(data))
|
, data_(std::move(data))
|
||||||
|
|||||||
@@ -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) {
|
||||||
auto converted = std::wstring_convert<std::codecvt_utf8<int32_t>, int32_t>().from_bytes(s);
|
bool is_ascii = true;
|
||||||
return std::u32string(reinterpret_cast<char32_t const*>(converted.data()));
|
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);
|
||||||
|
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
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
+58
-59
@@ -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,26 +150,31 @@ 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
|
||||||
return;
|
// variant types below.
|
||||||
}
|
if (aggr) {
|
||||||
decltype(p.tokens_) p_tokens_filtered;
|
auto aggr_type = IfcUtil::make_aggregate(IfcUtil::from_parameter_type(aggr->type_of_element()));
|
||||||
std::vector<uint8_t> first_type;
|
if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_INT) {
|
||||||
get_token_type(first_type, p.tokens_.front());
|
fn(std::vector<int>{});
|
||||||
std::copy_if(
|
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) {
|
||||||
p.tokens_.begin(),
|
fn(std::vector<double>{});
|
||||||
p.tokens_.end(),
|
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_STRING) {
|
||||||
std::back_inserter(p_tokens_filtered),
|
fn(std::vector<std::string>{});
|
||||||
[first_type](auto& x) {
|
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_BINARY) {
|
||||||
std::vector<uint8_t> nth_type;
|
fn(std::vector<boost::dynamic_bitset<>>{});
|
||||||
get_token_type(nth_type, x);
|
} else if (aggr_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
|
||||||
return can_coerce(first_type, nth_type);
|
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;
|
||||||
if (p.tokens_.size() != p_tokens_filtered.size()) {
|
|
||||||
// warning
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef boost::variant<
|
typedef boost::variant<
|
||||||
@@ -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 (aggregate_storage.which() == 0) {
|
||||||
|
aggregate_storage = std::vector<std::decay_t<decltype(v)>>{ v };
|
||||||
|
} else {
|
||||||
|
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>) {
|
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::Token>) {
|
||||||
// @todo get aggregate of enumeration
|
// @todo get aggregate of enumeration
|
||||||
dispatch_token(v, nullptr, [&aggregate_storage](auto v) {
|
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);
|
||||||
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) {
|
|
||||||
aggregate_storage = std::vector<std::decay_t<decltype(v)>>{ v };
|
|
||||||
} else {
|
|
||||||
boost::get< std::vector<std::decay_t<decltype(v)>>>(aggregate_storage).push_back(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, [&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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
+103
-355
@@ -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,27 +1922,12 @@ 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);
|
||||||
bytype_excl_.erase(ty);
|
if (it->second->size() == 0) {
|
||||||
}
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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,9 +2010,13 @@ 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) {
|
||||||
ret->push(instance_by_id(i));
|
for (auto& i : it->second) {
|
||||||
|
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,39 +2154,43 @@ 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);
|
||||||
|
|
||||||
if (attribute_index == -1) {
|
visit_subtypes(type->as_entity(), [this, attribute_index, instance_id, &return_value](const IfcParse::declaration* ent) {
|
||||||
auto lower = byref_.lower_bound({instance_id, type->index_in_schema(), -1});
|
if (attribute_index == -1) {
|
||||||
auto upper = byref_.upper_bound({instance_id, type->index_in_schema(), std::numeric_limits<int>::max()});
|
auto lower = byref_excl_.lower_bound({ instance_id, ent->index_in_schema(), -1 });
|
||||||
|
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) {
|
||||||
return_value->push(instance_by_id(i));
|
return_value->push(instance_by_id(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto it = byref_excl_.find({ instance_id, ent->index_in_schema(), attribute_index });
|
||||||
|
if (it != byref_excl_.end()) {
|
||||||
|
for (auto& i : it->second) {
|
||||||
|
return_value->push(instance_by_id(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
});
|
||||||
auto it = byref_.find({instance_id, type->index_in_schema(), attribute_index});
|
|
||||||
if (it != byref_.end()) {
|
|
||||||
for (auto& i : it->second) {
|
|
||||||
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() << "=";
|
||||||
}
|
}
|
||||||
out << declaration().name_uc();
|
if (upper) {
|
||||||
|
out << declaration().name_uc();
|
||||||
|
} else {
|
||||||
|
out << declaration().name();
|
||||||
|
}
|
||||||
data().toString(out, upper, ent);
|
data().toString(out, upper, ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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&);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user