mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +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) {
|
||||
auto decl = f.schema()->declaration_by_name(entity);
|
||||
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")) {
|
||||
IfcParse::IfcGlobalId guid;
|
||||
latebound_access::set(inst, "GlobalId", (std::string) guid);
|
||||
|
||||
@@ -55,6 +55,8 @@
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR
|
||||
|
||||
#ifndef IFCGEOMITERATOR_H
|
||||
#define IFCGEOMITERATOR_H
|
||||
|
||||
|
||||
@@ -86,20 +86,17 @@ class IFC_PARSE_API IfcBaseInterface {
|
||||
};
|
||||
|
||||
class IFC_PARSE_API IfcBaseClass : public virtual IfcBaseInterface {
|
||||
protected:
|
||||
uint32_t identity_;
|
||||
protected:
|
||||
static std::atomic_uint32_t counter_;
|
||||
|
||||
|
||||
uint32_t identity_;
|
||||
public:
|
||||
uint32_t id_;
|
||||
IfcParse::IfcFile* file_;
|
||||
protected:
|
||||
IfcEntityInstanceData data_;
|
||||
|
||||
static bool is_null(const IfcBaseClass* not_this) {
|
||||
return not_this == nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
uint32_t id_;
|
||||
IfcParse::IfcFile* file_;
|
||||
|
||||
public:
|
||||
IfcBaseClass(IfcEntityInstanceData&& data)
|
||||
: identity_(counter_++)
|
||||
, 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
|
||||
|
||||
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);
|
||||
return std::u32string(reinterpret_cast<char32_t const*>(converted.data()));
|
||||
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);
|
||||
return std::u32string(reinterpret_cast<char32_t const*>(converted.data()));
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
std::u32string IfcUtil::convert_utf8_to_utf32(const std::string& string) {
|
||||
return std::wstring_convert<std::codecvt_utf8<std::u32string::value_type>, std::u32string::value_type>().from_bytes(string);
|
||||
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 {
|
||||
return std::wstring_convert<std::codecvt_utf8<std::u32string::value_type>, std::u32string::value_type>().from_bytes(s);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -167,6 +167,10 @@ class IFC_PARSE_API IfcEntityInstanceData {
|
||||
: storage_(std::move(storage))
|
||||
{}
|
||||
|
||||
IfcEntityInstanceData(IfcEntityInstanceData&& other) noexcept
|
||||
: storage_(std::move(other.storage_))
|
||||
{}
|
||||
|
||||
IfcEntityInstanceData(const IfcEntityInstanceData& data);
|
||||
|
||||
IfcEntityInstanceData& operator=(IfcEntityInstanceData&& other) {
|
||||
|
||||
+58
-59
@@ -141,7 +141,7 @@ namespace {
|
||||
} else if (t.type == IfcParse::Token_FLOAT) {
|
||||
fn(IfcParse::TokenFunc::asFloat(t));
|
||||
} 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) {
|
||||
fn(IfcParse::TokenFunc::asInt(t));
|
||||
} else if (t.type == IfcParse::Token_STRING) {
|
||||
@@ -150,26 +150,31 @@ namespace {
|
||||
}
|
||||
|
||||
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()) {
|
||||
// @todo based on type create appropate empty aggregate
|
||||
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);
|
||||
// @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));
|
||||
}
|
||||
}
|
||||
);
|
||||
if (p.tokens_.size() != p_tokens_filtered.size()) {
|
||||
// warning
|
||||
return;
|
||||
}
|
||||
|
||||
typedef boost::variant<
|
||||
@@ -188,25 +193,28 @@ namespace {
|
||||
|
||||
possible_aggregation_types_t aggregate_storage;
|
||||
|
||||
for (auto& t : p_tokens_filtered) {
|
||||
boost::apply_visitor([&aggregate_storage](auto& v) {
|
||||
auto append_to_aggregate_storage = [&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>) {
|
||||
// @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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
});
|
||||
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*>) {
|
||||
/*construct_(*v, [&aggregate_storage](auto& v) {
|
||||
if (aggregate_storage.which() == 0) {
|
||||
@@ -217,11 +225,7 @@ namespace {
|
||||
});*/
|
||||
// Too deeply nested list
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
append_to_aggregate_storage(v);
|
||||
}
|
||||
}, t);
|
||||
}
|
||||
@@ -246,17 +250,8 @@ IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_re
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
std::vector<IfcUtil::ArgumentType> attr_types;
|
||||
std::transform(
|
||||
parameter_types.begin(),
|
||||
parameter_types.end(),
|
||||
std::back_inserter(attr_types),
|
||||
IfcUtil::from_parameter_type
|
||||
);
|
||||
|
||||
|
||||
if (decl && (tokens_.size() != attr_types.size())) {
|
||||
if (decl && (tokens_.size() != parameter_types.size())) {
|
||||
// warning
|
||||
}
|
||||
|
||||
@@ -265,17 +260,15 @@ IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_re
|
||||
}
|
||||
|
||||
storage_t storage(decl
|
||||
? (std::min)(attr_types.size(), tokens_.size())
|
||||
? (std::min)(parameter_types.size(), tokens_.size())
|
||||
: tokens_.size()
|
||||
);
|
||||
|
||||
auto it = tokens_.begin();
|
||||
auto jt = attr_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;
|
||||
// @todo coerce to expected type, e.g empty -> std::vector<int>, bool -> logical
|
||||
// auto& attr_type = *jt;
|
||||
const IfcParse::parameter_type* param_type = nullptr;
|
||||
if (decl) {
|
||||
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) {
|
||||
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) {
|
||||
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(
|
||||
// @todo previously this was storage but apparently the
|
||||
// pointer is not constant with the moving and temporary nature
|
||||
// maybe it ought to be and in that case a pointer is more direct
|
||||
MutableAttributeValue{ name, index },
|
||||
unresolved_references::value_type::second_type{v}
|
||||
v
|
||||
));
|
||||
} else {
|
||||
storage.set(index, v);
|
||||
}
|
||||
});
|
||||
} 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>>) {
|
||||
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>>>) {
|
||||
@@ -314,7 +313,7 @@ IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_re
|
||||
}, token);
|
||||
|
||||
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<uint32_t, IfcUtil::IfcBaseClass*> entity_by_iden_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 {
|
||||
INSTANCE_ID,
|
||||
INSTANCE_TYPE,
|
||||
@@ -165,10 +165,10 @@ class IFC_PARSE_API IfcFile {
|
||||
entity_by_id_t byid_;
|
||||
// this is for simple types
|
||||
entity_by_iden_t byidentity_;
|
||||
entities_by_type_t bytype_;
|
||||
// entities_by_type_t bytype_;
|
||||
entities_by_type_t bytype_excl_;
|
||||
entities_by_ref_t byref_;
|
||||
entities_by_ref_excl_t byref_excl_;
|
||||
// entities_by_ref_t byref_;
|
||||
entities_by_ref_t byref_excl_;
|
||||
entity_by_guid_t byguid_;
|
||||
entity_entity_map_t entity_file_map_;
|
||||
|
||||
@@ -222,8 +222,8 @@ class IFC_PARSE_API IfcFile {
|
||||
type_iterator types_begin() const;
|
||||
type_iterator types_end() const;
|
||||
|
||||
type_iterator types_incl_super_begin() const;
|
||||
type_iterator types_incl_super_end() const;
|
||||
// type_iterator types_incl_super_begin() const;
|
||||
// type_iterator types_incl_super_end() const;
|
||||
|
||||
/// Returns all entities in the file that match the template argument.
|
||||
/// 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(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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR
|
||||
|
||||
#include "IfcLogger.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) {
|
||||
// static std::mutex mtx;
|
||||
// std::lock_guard<std::mutex> lock(mtx);
|
||||
if (type < verbosity_) {
|
||||
return;
|
||||
}
|
||||
|
||||
static std::mutex mtx;
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
|
||||
if (type == LOG_PERF) {
|
||||
if (!first_timepoint_) {
|
||||
@@ -166,7 +172,7 @@ void Logger::Message(Logger::Severity type, const std::string& message, const If
|
||||
if (type > max_severity_) {
|
||||
max_severity_ = type;
|
||||
}
|
||||
if (((log2_ != nullptr) || (wlog2_ != nullptr)) && type >= verbosity_) {
|
||||
if (((log2_ != nullptr) || (wlog2_ != nullptr))) {
|
||||
if (format_ == FMT_PLAIN) {
|
||||
if (log2_ != nullptr) {
|
||||
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();
|
||||
}
|
||||
|
||||
/*
|
||||
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 return_value = 0;
|
||||
|
||||
@@ -737,7 +716,8 @@ void IfcParse::IfcFile::load(unsigned entity_instance_name, const IfcParse::enti
|
||||
try {
|
||||
parse_context ps;
|
||||
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));
|
||||
context.push(simple_type_instance);
|
||||
simple_type_instance->file_ = this;
|
||||
@@ -766,10 +746,6 @@ IfcEntityInstanceData IfcParse::read(unsigned int i, IfcFile* f) {
|
||||
parse_context pc;
|
||||
f->load(i, ty->as_entity(), pc, -1);
|
||||
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() {
|
||||
@@ -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) {
|
||||
// Assume a check on token type has already been performed
|
||||
const auto* e = from_entity;
|
||||
byref_excl_[t.value_int].push_back(id_from);
|
||||
while (e != nullptr) {
|
||||
byref_[{t.value_int, e->index_in_schema(), attribute_index}].push_back(id_from);
|
||||
e = e->supertype();
|
||||
}
|
||||
byref_excl_[{t.value_int, e->index_in_schema(), attribute_index}].push_back(id_from);
|
||||
}
|
||||
|
||||
void IfcParse::IfcFile::register_inverse(unsigned id_from, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass* inst, int attribute_index) {
|
||||
const auto* e = from_entity;
|
||||
byref_excl_[inst->id()].push_back(id_from);
|
||||
while (e != nullptr) {
|
||||
byref_[{inst->id(), e->index_in_schema(), attribute_index}].push_back(id_from);
|
||||
e = e->supertype();
|
||||
}
|
||||
byref_excl_[{inst->id(), e->index_in_schema(), attribute_index}].push_back(id_from);
|
||||
}
|
||||
|
||||
void IfcParse::IfcFile::unregister_inverse(unsigned id_from, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass* inst, int attribute_index) {
|
||||
const auto* entity = from_entity;
|
||||
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>& ids = byref_excl_[{inst->id(), from_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.
|
||||
@@ -917,7 +872,7 @@ namespace {
|
||||
}
|
||||
void operator()(const IfcUtil::IfcBaseClass* const& i) {
|
||||
if (i->declaration().as_entity() == nullptr) {
|
||||
i->data().toString(data_, true);
|
||||
i->toString(data_, upper_);
|
||||
} else {
|
||||
data_ << "#" << i->id();
|
||||
}
|
||||
@@ -1025,20 +980,6 @@ namespace {
|
||||
void IfcEntityInstanceData::toString(std::ostream& ss, bool upper, const entity* decl) const {
|
||||
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 << "(";
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
// Register inverse indices in file
|
||||
register_inverse_visitor visitor(*file_, this);
|
||||
@@ -1385,16 +1185,19 @@ IfcFile::IfcFile(const std::string& fn, bool mmap) {
|
||||
}
|
||||
#else
|
||||
IfcFile::IfcFile(const std::string& path) {
|
||||
initialize_(new IfcSpfStream(path));
|
||||
IfcSpfStream s(path);
|
||||
initialize_(&s);
|
||||
}
|
||||
#endif
|
||||
|
||||
IfcFile::IfcFile(std::istream& stream, int length) {
|
||||
initialize_(new IfcSpfStream(stream, length));
|
||||
IfcSpfStream s(stream, length);
|
||||
initialize_(&s);
|
||||
}
|
||||
|
||||
IfcFile::IfcFile(void* data, int length) {
|
||||
initialize_(new IfcSpfStream(data, length));
|
||||
IfcSpfStream s(data, length);
|
||||
initialize_(&s);
|
||||
}
|
||||
|
||||
IfcFile::IfcFile(IfcParse::IfcSpfStream* s) {
|
||||
@@ -1493,7 +1296,7 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
|
||||
|
||||
parse_context ps;
|
||||
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->id_ = current_id;
|
||||
|
||||
@@ -1525,27 +1328,10 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
|
||||
const IfcParse::declaration* ty = &instance->declaration();
|
||||
|
||||
{
|
||||
aggregate_of_instance::ptr insts = instances_by_type_excl_subtypes(ty);
|
||||
if (!insts) {
|
||||
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;
|
||||
if (bytype_excl_.find(ty) == bytype_excl_.end()) {
|
||||
bytype_excl_[ty].reset(new aggregate_of_instance());
|
||||
}
|
||||
bytype_excl_[ty]->push(instance);
|
||||
}
|
||||
|
||||
if (byid_.find(current_id) != byid_.end()) {
|
||||
@@ -1588,6 +1374,8 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
|
||||
|
||||
Logger::Status("\rDone scanning file ");
|
||||
|
||||
delete tokens;
|
||||
|
||||
for (auto& p : references_to_resolve) {
|
||||
boost::apply_visitor([this, &p](auto& v) {
|
||||
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));
|
||||
} 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);
|
||||
instances->reserve(v.size());
|
||||
for (auto& p : v) {
|
||||
instances->push(boost::apply_visitor([this](auto inst) {
|
||||
IfcUtil::IfcBaseClass* ptr;
|
||||
@@ -1810,7 +1599,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
|
||||
IfcFile* other_file = entity->file_;
|
||||
|
||||
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
|
||||
// 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());
|
||||
}
|
||||
byguid_[guid] = new_entity;
|
||||
} catch (const IfcException& ex) {
|
||||
} catch (const std::exception& ex) {
|
||||
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();
|
||||
|
||||
if (ty->as_entity() != nullptr) {
|
||||
aggregate_of_instance::ptr insts = instances_by_type_excl_subtypes(ty);
|
||||
if (!insts) {
|
||||
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;
|
||||
if (bytype_excl_.find(ty) == bytype_excl_.end()) {
|
||||
bytype_excl_[ty].reset(new aggregate_of_instance());
|
||||
}
|
||||
bytype_excl_[ty]->push(new_entity);
|
||||
}
|
||||
|
||||
if (ty->as_entity() != nullptr) {
|
||||
@@ -2106,11 +1877,11 @@ void IfcFile::process_deletion_() {
|
||||
}
|
||||
|
||||
if (!batch_mode_) {
|
||||
byref_.erase(
|
||||
byref_.lower_bound({id, -1, -1}),
|
||||
byref_.upper_bound({id, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()}));
|
||||
byref_excl_.erase(
|
||||
byref_excl_.lower_bound({id, -1, -1}),
|
||||
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.
|
||||
// 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).
|
||||
if (name != 0) {
|
||||
{
|
||||
auto lower = byref_.lower_bound({name, -1, -1});
|
||||
auto upper = byref_.upper_bound({name, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()});
|
||||
auto lower = byref_excl_.lower_bound({name, -1, -1});
|
||||
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) {
|
||||
auto& ids = byref_it->second;
|
||||
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();
|
||||
|
||||
{
|
||||
aggregate_of_instance::ptr instances_of_same_type = instances_by_type_excl_subtypes(ty);
|
||||
instances_of_same_type->remove(entity);
|
||||
if (instances_of_same_type->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;
|
||||
auto it = bytype_excl_.find(ty);
|
||||
if (it != bytype_excl_.end()) {
|
||||
it->second->remove(entity);
|
||||
if (it->second->size() == 0) {
|
||||
bytype_excl_.erase(ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2196,24 +1945,8 @@ void IfcFile::process_deletion_() {
|
||||
}
|
||||
|
||||
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();) {
|
||||
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) {
|
||||
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();
|
||||
@@ -2232,14 +1965,40 @@ void IfcFile::process_deletion_() {
|
||||
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) {
|
||||
entities_by_type_t::const_iterator it = bytype_.find(t);
|
||||
return (it == bytype_.end()) ? aggregate_of_instance::ptr() : it->second;
|
||||
aggregate_of_instance::ptr insts(new aggregate_of_instance);
|
||||
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) {
|
||||
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) {
|
||||
@@ -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) {
|
||||
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);
|
||||
for (auto& i : byref_excl_[t]) {
|
||||
ret->push(instance_by_id(i));
|
||||
for (auto it = lower; it != upper; ++it) {
|
||||
for (auto& i : it->second) {
|
||||
ret->push(instance_by_id(i));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -2286,8 +2049,6 @@ IfcFile::~IfcFile() {
|
||||
for (auto* entity : entities_to_delete) {
|
||||
delete entity;
|
||||
}
|
||||
delete stream;
|
||||
delete tokens;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
@@ -2362,8 +2115,8 @@ std::string IfcFile::createTimestamp() const {
|
||||
std::vector<int> IfcFile::get_inverse_indices(int instance_id) {
|
||||
std::vector<int> return_value;
|
||||
|
||||
auto lower = byref_.lower_bound({instance_id, -1, -1});
|
||||
auto upper = byref_.upper_bound({instance_id, std::numeric_limits<int>::max(), std::numeric_limits<int>::max()});
|
||||
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()});
|
||||
|
||||
// Mapping of instance id to attribute offset.
|
||||
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) {
|
||||
// @todo is this mutex still necessary?
|
||||
static std::mutex mtx;
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
|
||||
if (type == nullptr && attribute_index == -1) {
|
||||
return instances_by_reference(instance_id);
|
||||
}
|
||||
|
||||
aggregate_of_instance::ptr return_value(new aggregate_of_instance);
|
||||
|
||||
if (attribute_index == -1) {
|
||||
auto lower = byref_.lower_bound({instance_id, type->index_in_schema(), -1});
|
||||
auto upper = byref_.upper_bound({instance_id, type->index_in_schema(), std::numeric_limits<int>::max()});
|
||||
visit_subtypes(type->as_entity(), [this, attribute_index, instance_id, &return_value](const IfcParse::declaration* ent) {
|
||||
if (attribute_index == -1) {
|
||||
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& i : it->second) {
|
||||
return_value->push(instance_by_id(i));
|
||||
for (auto it = lower; it != upper; ++it) {
|
||||
for (auto& i : it->second) {
|
||||
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;
|
||||
}
|
||||
|
||||
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() {
|
||||
@@ -2531,11 +2288,7 @@ void IfcParse::IfcFile::build_inverses_(IfcUtil::IfcBaseClass* inst) {
|
||||
if (attr->declaration().as_entity() != nullptr) {
|
||||
unsigned entity_attribute_id = attr->id();
|
||||
const auto* decl = inst->declaration().as_entity();
|
||||
byref_excl_[entity_attribute_id].push_back(inst->id());
|
||||
while (decl != nullptr) {
|
||||
byref_[{entity_attribute_id, decl->index_in_schema(), idx}].push_back(inst->id());
|
||||
decl = decl->supertype();
|
||||
}
|
||||
byref_excl_[{entity_attribute_id, decl->index_in_schema(), idx}].push_back(inst->id());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2552,15 +2305,6 @@ std::atomic_uint32_t IfcUtil::IfcBaseClass::counter_(0);
|
||||
|
||||
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) {
|
||||
data_.storage_.set(index, Blank{});
|
||||
}
|
||||
@@ -2571,7 +2315,11 @@ void IfcUtil::IfcBaseClass::toString(std::ostream& out, bool upper) const
|
||||
if (ent) {
|
||||
out << "#" << as<IfcUtil::IfcBaseEntity>()->id() << "=";
|
||||
}
|
||||
out << declaration().name_uc();
|
||||
if (upper) {
|
||||
out << declaration().name_uc();
|
||||
} else {
|
||||
out << declaration().name();
|
||||
}
|
||||
data().toString(out, upper, ent);
|
||||
}
|
||||
|
||||
|
||||
@@ -152,11 +152,11 @@ IfcParse::schema_definition::~schema_definition() {
|
||||
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) {
|
||||
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) {
|
||||
|
||||
@@ -507,7 +507,7 @@ class IFC_PARSE_API schema_definition {
|
||||
|
||||
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&);
|
||||
|
||||
@@ -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) {
|
||||
// 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 <tuple>
|
||||
|
||||
#include "IfcException.h"
|
||||
|
||||
namespace impl {
|
||||
// Trait to detect unique_ptr
|
||||
template <typename...> struct is_unique_ptr : std::false_type {};
|
||||
@@ -216,7 +218,13 @@ public:
|
||||
template<typename T>
|
||||
const T& get(std::size_t index) const {
|
||||
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;
|
||||
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...>> &>())){};
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@@ -186,6 +186,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
|
||||
return ts;
|
||||
}
|
||||
|
||||
/*
|
||||
std::vector<std::string> types_with_super() const {
|
||||
const size_t n = std::distance($self->types_incl_super_begin(), $self->types_incl_super_end());
|
||||
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);
|
||||
return ts;
|
||||
}
|
||||
*/
|
||||
|
||||
std::string schema_name() const {
|
||||
if ($self->schema() == 0) return "";
|
||||
@@ -368,7 +370,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
|
||||
void setArgumentAsNull(unsigned int i) {
|
||||
bool is_optional = $self->declaration().as_entity()->attribute_by_index(i)->optional();
|
||||
if (is_optional) {
|
||||
self->data().storage_.set(i, Blank{});
|
||||
self->set_attribute_value(i, Blank{});
|
||||
} else {
|
||||
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) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
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) ) ) {
|
||||
self->data().storage_.set(i, v);
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
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) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_BOOL) {
|
||||
self->data().storage_.set(i, v);
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
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) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_LOGICAL) {
|
||||
self->data().storage_.set(i, v);
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
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) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_DOUBLE) {
|
||||
self->data().storage_.set(i, v);
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
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) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
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) {
|
||||
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();
|
||||
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) {
|
||||
if (IfcUtil::valid_binary_string(a)) {
|
||||
boost::dynamic_bitset<> bits(a);
|
||||
self->data().storage_.set(i, bits);
|
||||
self->set_attribute_value(i, bits);
|
||||
} else {
|
||||
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) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_INT) {
|
||||
self->data().storage_.set(i, v);
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
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) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) {
|
||||
self->data().storage_.set(i, v);
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
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) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
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) {
|
||||
std::vector< boost::dynamic_bitset<> > bits;
|
||||
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");
|
||||
}
|
||||
}
|
||||
self->data().storage_.set(i, bits);
|
||||
self->set_attribute_value(i, bits);
|
||||
} else {
|
||||
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) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_ENTITY_INSTANCE) {
|
||||
self->data().storage_.set(i, v);
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
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) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
|
||||
self->data().storage_.set(i, v);
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
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) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT) {
|
||||
self->data().storage_.set(i, v);
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
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) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE) {
|
||||
self->data().storage_.set(i, v);
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
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) {
|
||||
IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i);
|
||||
if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) {
|
||||
self->data().storage_.set(i, v);
|
||||
self->set_attribute_value(i, v);
|
||||
} else {
|
||||
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::declaration* decl = schema->declaration_by_name(name);
|
||||
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)
|
||||
p = g.createIfcCartesianPoint((0.,0.))
|
||||
assert len(g.types()) == 1
|
||||
assert "IfcPoint" in g.types_with_super()
|
||||
g.remove(p)
|
||||
assert len(g.types()) == 0
|
||||
assert len(g.types_with_super()) == 0
|
||||
|
||||
# Some operations on ifcopenshell.entity_instance
|
||||
assert f[22].Id == ''
|
||||
@@ -92,6 +90,9 @@ assert f[288].ConnectedTo == (rel,)
|
||||
# Some operations on ifcopenshell.guid
|
||||
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
|
||||
tree_settings = ifcopenshell.geom.settings()
|
||||
tree_settings.set(tree_settings.DISABLE_OPENING_SUBTRACTIONS, True)
|
||||
|
||||
Reference in New Issue
Block a user