mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 22:33:33 +00:00
Initial attempt at shared pointer storage of instances and weap ptr access in python
This commit is contained in:
@@ -1508,51 +1508,47 @@ namespace latebound_access {
|
|||||||
IfcParse::IfcGlobalId guid;
|
IfcParse::IfcGlobalId guid;
|
||||||
latebound_access::set(inst, "GlobalId", (std::string) guid);
|
latebound_access::set(inst, "GlobalId", (std::string) guid);
|
||||||
}
|
}
|
||||||
return f.addEntity(inst);
|
return &*f.addEntity(inst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fix_quantities(IfcParse::IfcFile& f, bool no_progress, bool quiet, bool stderr_progress) {
|
void fix_quantities(IfcParse::IfcFile& f, bool no_progress, bool quiet, bool stderr_progress) {
|
||||||
{
|
{
|
||||||
auto delete_reversed = [&f](const aggregate_of_instance::ptr& insts) {
|
auto delete_range = [&f](const IfcParse::IfcFile::type_iterator_range_t& insts) {
|
||||||
if (!insts) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Lists are traversed back to front as the list may be mutated when
|
// Lists are traversed back to front as the list may be mutated when
|
||||||
// instances are removed from the grouping by type.
|
// instances are removed from the grouping by type.
|
||||||
for (auto it = insts->end() - 1; it >= insts->begin(); --it) {
|
for (auto it = insts.first; it != insts.second; ++it) {
|
||||||
IfcUtil::IfcBaseClass* const inst = *it;
|
f.removeEntity(&**it);
|
||||||
f.removeEntity(inst);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Delete quantities
|
// Delete quantities
|
||||||
auto quantities = f.instances_by_type("IfcPhysicalQuantity");
|
auto quantities = f.instances_by_type("IfcPhysicalQuantity");
|
||||||
if (quantities) {
|
for (auto& q : boost::make_iterator_range(quantities)) {
|
||||||
quantities = quantities->filtered({ f.schema()->declaration_by_name("IfcPhysicalComplexQuantity") });
|
// @todo test iterator invalidation
|
||||||
delete_reversed(quantities);
|
if (q->declaration().name() == "IfcPhysicalComplexQuantity") {
|
||||||
|
f.removeEntity(&*q);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete complexes
|
// Delete complexes
|
||||||
delete_reversed(f.instances_by_type("IfcPhysicalComplexQuantity"));
|
delete_range(f.instances_by_type("IfcPhysicalComplexQuantity"));
|
||||||
|
|
||||||
auto element_quantities = f.instances_by_type("IfcElementQuantity");
|
auto element_quantities = f.instances_by_type("IfcElementQuantity");
|
||||||
|
|
||||||
// Capture relationship nodes
|
// Capture relationship nodes
|
||||||
std::vector<IfcUtil::IfcBaseClass*> relationships;
|
std::vector<IfcUtil::IfcBaseClass*> relationships;
|
||||||
auto IfcRelDefinesByProperties = f.schema()->declaration_by_name("IfcRelDefinesByProperties");
|
auto IfcRelDefinesByProperties = f.schema()->declaration_by_name("IfcRelDefinesByProperties");
|
||||||
if (element_quantities) {
|
for (auto& eq : boost::make_iterator_range(element_quantities)) {
|
||||||
for (auto& eq : *element_quantities) {
|
auto rels = eq->data().getInverse(IfcRelDefinesByProperties, -1);
|
||||||
auto rels = eq->data().getInverse(IfcRelDefinesByProperties, -1);
|
for (auto& rel : *rels) {
|
||||||
for (auto& rel : *rels) {
|
relationships.push_back(rel);
|
||||||
relationships.push_back(rel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete element quantities
|
|
||||||
delete_reversed(element_quantities);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete element quantities
|
||||||
|
delete_range(element_quantities);
|
||||||
|
|
||||||
|
|
||||||
// Delete relationship nodes
|
// Delete relationship nodes
|
||||||
for (auto& rel : relationships) {
|
for (auto& rel : relationships) {
|
||||||
|
|||||||
+72
-30
@@ -68,10 +68,18 @@ class IFC_PARSE_API file_open_status {
|
|||||||
/// and provide access to the entities in an IFC file
|
/// and provide access to the entities in an IFC file
|
||||||
class IFC_PARSE_API IfcFile {
|
class IFC_PARSE_API IfcFile {
|
||||||
public:
|
public:
|
||||||
typedef std::map<const IfcParse::declaration*, aggregate_of_instance::ptr> entities_by_type_t;
|
#ifndef NO_SHARED_POINTER_STORAGE
|
||||||
typedef boost::unordered_map<unsigned int, IfcUtil::IfcBaseClass*> entity_by_id_t;
|
typedef std::shared_ptr<IfcUtil::IfcBaseClass> instance_storage_type;
|
||||||
typedef boost::unordered_map<uint32_t, IfcUtil::IfcBaseClass*> entity_by_iden_t;
|
typedef std::weak_ptr<IfcUtil::IfcBaseClass> instance_reference_type;
|
||||||
typedef std::map<std::string, IfcUtil::IfcBaseClass*> entity_by_guid_t;
|
#else
|
||||||
|
typedef IfcUtil::IfcBaseClass* instance_storage_type;
|
||||||
|
typedef IfcUtil::IfcBaseClass* instance_reference_type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef std::multimap<const IfcParse::declaration*, instance_storage_type> entities_by_type_t;
|
||||||
|
typedef boost::unordered_map<unsigned int, instance_storage_type> entity_by_id_t;
|
||||||
|
typedef boost::unordered_map<uint32_t, instance_storage_type> entity_by_iden_t;
|
||||||
|
typedef std::map<std::string, instance_storage_type> entity_by_guid_t;
|
||||||
typedef std::tuple<int, int, int> inverse_attr_record;
|
typedef std::tuple<int, int, int> inverse_attr_record;
|
||||||
enum INVERSE_ATTR {
|
enum INVERSE_ATTR {
|
||||||
INSTANCE_ID,
|
INSTANCE_ID,
|
||||||
@@ -80,9 +88,9 @@ class IFC_PARSE_API IfcFile {
|
|||||||
};
|
};
|
||||||
typedef std::map<inverse_attr_record, std::vector<int>> entities_by_ref_t;
|
typedef std::map<inverse_attr_record, std::vector<int>> entities_by_ref_t;
|
||||||
typedef std::map<int, std::vector<int>> entities_by_ref_excl_t;
|
typedef std::map<int, std::vector<int>> entities_by_ref_excl_t;
|
||||||
typedef std::map<unsigned int, aggregate_of_instance::ptr> ref_map_t;
|
|
||||||
typedef entity_by_id_t::const_iterator const_iterator;
|
typedef entity_by_id_t::const_iterator const_iterator;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
class type_iterator : private entities_by_type_t::const_iterator {
|
class type_iterator : private entities_by_type_t::const_iterator {
|
||||||
public:
|
public:
|
||||||
type_iterator() : entities_by_type_t::const_iterator(){};
|
type_iterator() : entities_by_type_t::const_iterator(){};
|
||||||
@@ -90,16 +98,35 @@ class IFC_PARSE_API IfcFile {
|
|||||||
type_iterator(const entities_by_type_t::const_iterator& iter)
|
type_iterator(const entities_by_type_t::const_iterator& iter)
|
||||||
: entities_by_type_t::const_iterator(iter){};
|
: entities_by_type_t::const_iterator(iter){};
|
||||||
|
|
||||||
entities_by_type_t::key_type const* operator->() const {
|
T const* operator->() const {
|
||||||
return &entities_by_type_t::const_iterator::operator->()->first;
|
if constexpr (std::is_same_v<T, entities_by_type_t::key_type>) {
|
||||||
|
return &entities_by_type_t::const_iterator::operator->()->first;
|
||||||
|
} else {
|
||||||
|
return &entities_by_type_t::const_iterator::operator->()->second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entities_by_type_t::key_type const& operator*() const {
|
T const& operator*() const {
|
||||||
return entities_by_type_t::const_iterator::operator*().first;
|
if constexpr (std::is_same_v<T, entities_by_type_t::key_type>) {
|
||||||
|
return entities_by_type_t::const_iterator::operator*().first;
|
||||||
|
} else {
|
||||||
|
return entities_by_type_t::const_iterator::operator*().second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type_iterator& operator++() {
|
type_iterator& operator++() {
|
||||||
entities_by_type_t::const_iterator::operator++();
|
auto k = **this;
|
||||||
|
// @todo we changed from map(aggregate) to multimap(instance)
|
||||||
|
// (why again?) so now we need to keep iterating in our type
|
||||||
|
// iterator. Given the distribution of entity types, this
|
||||||
|
// likely has performance impliciations, but this function is
|
||||||
|
// probably hardly ever used.
|
||||||
|
do {
|
||||||
|
entities_by_type_t::const_iterator::operator++();
|
||||||
|
if constexpr (std::is_same_v<T, entities_by_type_t::value_type>) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (k == **this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,6 +143,8 @@ class IFC_PARSE_API IfcFile {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::pair<type_iterator<entities_by_type_t::value_type::second_type>, type_iterator<entities_by_type_t::value_type::second_type>> type_iterator_range_t;
|
||||||
|
|
||||||
static bool lazy_load_;
|
static bool lazy_load_;
|
||||||
static bool lazy_load() { return lazy_load_; }
|
static bool lazy_load() { return lazy_load_; }
|
||||||
static void lazy_load(bool b) { lazy_load_ = b; }
|
static void lazy_load(bool b) { lazy_load_ = b; }
|
||||||
@@ -125,7 +154,7 @@ class IFC_PARSE_API IfcFile {
|
|||||||
static void guid_map(bool b) { guid_map_ = b; }
|
static void guid_map(bool b) { guid_map_ = b; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::map<uint32_t, IfcUtil::IfcBaseClass*> entity_entity_map_t;
|
typedef std::map<uint32_t, instance_storage_type> entity_entity_map_t;
|
||||||
|
|
||||||
bool parsing_complete_;
|
bool parsing_complete_;
|
||||||
file_open_status good_ = file_open_status::SUCCESS;
|
file_open_status good_ = file_open_status::SUCCESS;
|
||||||
@@ -192,48 +221,50 @@ class IFC_PARSE_API IfcFile {
|
|||||||
/// with the highest id (EXPRESS ENTITY_INSTANCE_NAME)
|
/// with the highest id (EXPRESS ENTITY_INSTANCE_NAME)
|
||||||
const_iterator end() const;
|
const_iterator end() const;
|
||||||
|
|
||||||
type_iterator types_begin() const;
|
type_iterator<entities_by_type_t::key_type> types_begin() const;
|
||||||
type_iterator types_end() const;
|
type_iterator<entities_by_type_t::key_type> types_end() const;
|
||||||
|
|
||||||
type_iterator types_incl_super_begin() const;
|
type_iterator<entities_by_type_t::key_type> types_incl_super_begin() const;
|
||||||
type_iterator types_incl_super_end() const;
|
type_iterator<entities_by_type_t::key_type> 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:
|
||||||
/// IfcWall will also return IfcWallStandardCase entities
|
/// IfcWall will also return IfcWallStandardCase entities
|
||||||
template <class T>
|
template <class T>
|
||||||
typename T::list::ptr instances_by_type() {
|
typename T::list::ptr instances_by_type() {
|
||||||
aggregate_of_instance::ptr untyped_list = instances_by_type(&T::Class());
|
auto range = instances_by_type(&T::Class());
|
||||||
if (untyped_list) {
|
typename T::list::ptr vec(new typename T::list);
|
||||||
return untyped_list->as<T>();
|
for (auto it = range.first; it != range.second; ++it) {
|
||||||
|
vec->push((*it)->template as<T>());
|
||||||
}
|
}
|
||||||
return typename T::list::ptr(new typename T::list);
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
typename T::list::ptr instances_by_type_excl_subtypes() {
|
typename T::list::ptr instances_by_type_excl_subtypes() {
|
||||||
aggregate_of_instance::ptr untyped_list = instances_by_type_excl_subtypes(&T::Class());
|
auto range = instances_by_type_excl_subtypes(&T::Class());
|
||||||
if (untyped_list) {
|
typename T::list::ptr vec(new typename T::list);
|
||||||
return untyped_list->as<T>();
|
for (auto it = range.first; it != range.second; ++it) {
|
||||||
|
vec->push((*it)->template as<T>());
|
||||||
}
|
}
|
||||||
return typename T::list::ptr(new typename T::list);
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns all entities in the file that match the positional argument.
|
/// Returns all entities in the file that match the positional argument.
|
||||||
/// NOTE: This also returns subtypes of the requested type, for example:
|
/// NOTE: This also returns subtypes of the requested type, for example:
|
||||||
/// IfcWall will also return IfcWallStandardCase entities
|
/// IfcWall will also return IfcWallStandardCase entities
|
||||||
aggregate_of_instance::ptr instances_by_type(const IfcParse::declaration*);
|
type_iterator_range_t instances_by_type(const IfcParse::declaration*);
|
||||||
|
|
||||||
/// Returns all entities in the file that match the positional argument.
|
/// Returns all entities in the file that match the positional argument.
|
||||||
aggregate_of_instance::ptr instances_by_type_excl_subtypes(const IfcParse::declaration*);
|
type_iterator_range_t instances_by_type_excl_subtypes(const IfcParse::declaration*);
|
||||||
|
|
||||||
/// Returns all entities in the file that match the positional argument.
|
/// Returns all entities in the file that match the positional argument.
|
||||||
/// NOTE: This also returns subtypes of the requested type, for example:
|
/// NOTE: This also returns subtypes of the requested type, for example:
|
||||||
/// IfcWall will also return IfcWallStandardCase entities
|
/// IfcWall will also return IfcWallStandardCase entities
|
||||||
aggregate_of_instance::ptr instances_by_type(const std::string& type);
|
type_iterator_range_t instances_by_type(const std::string& type);
|
||||||
|
|
||||||
/// Returns all entities in the file that match the positional argument.
|
/// Returns all entities in the file that match the positional argument.
|
||||||
aggregate_of_instance::ptr instances_by_type_excl_subtypes(const std::string& type);
|
type_iterator_range_t instances_by_type_excl_subtypes(const std::string& type);
|
||||||
|
|
||||||
/// Returns all entities in the file that reference the id
|
/// Returns all entities in the file that reference the id
|
||||||
aggregate_of_instance::ptr instances_by_reference(int id);
|
aggregate_of_instance::ptr instances_by_reference(int id);
|
||||||
@@ -241,8 +272,10 @@ class IFC_PARSE_API IfcFile {
|
|||||||
/// Returns the entity with the specified id
|
/// Returns the entity with the specified id
|
||||||
IfcUtil::IfcBaseClass* instance_by_id(int id);
|
IfcUtil::IfcBaseClass* instance_by_id(int id);
|
||||||
|
|
||||||
|
IfcFile::instance_storage_type instance_by_id_2(int id);
|
||||||
|
|
||||||
/// Returns the entity with the specified GlobalId
|
/// Returns the entity with the specified GlobalId
|
||||||
IfcUtil::IfcBaseClass* instance_by_guid(const std::string& guid);
|
IfcFile::instance_storage_type instance_by_guid(const std::string& guid);
|
||||||
|
|
||||||
/// Performs a depth-first traversal, returning all entity instance
|
/// Performs a depth-first traversal, returning all entity instance
|
||||||
/// attributes as a flat list. NB: includes the root instance specified
|
/// attributes as a flat list. NB: includes the root instance specified
|
||||||
@@ -274,7 +307,7 @@ class IFC_PARSE_API IfcFile {
|
|||||||
|
|
||||||
void recalculate_id_counter();
|
void recalculate_id_counter();
|
||||||
|
|
||||||
IfcUtil::IfcBaseClass* addEntity(IfcUtil::IfcBaseClass* entity, int id = -1);
|
IfcFile::instance_storage_type addEntity(IfcUtil::IfcBaseClass* entity, int id = -1);
|
||||||
void addEntities(aggregate_of_instance::ptr entities);
|
void addEntities(aggregate_of_instance::ptr entities);
|
||||||
|
|
||||||
void batch() { batch_mode_ = true; }
|
void batch() { batch_mode_ = true; }
|
||||||
@@ -327,13 +360,22 @@ IFC_PARSE_API IfcFile* parse_ifcxml(const std::string& filename);
|
|||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template <>
|
template <>
|
||||||
struct iterator_traits<IfcParse::IfcFile::type_iterator> {
|
struct iterator_traits<IfcParse::IfcFile::type_iterator<IfcParse::IfcFile::entities_by_type_t::key_type>> {
|
||||||
typedef ptrdiff_t difference_type;
|
typedef ptrdiff_t difference_type;
|
||||||
typedef const IfcParse::declaration* value_type;
|
typedef const IfcParse::declaration* value_type;
|
||||||
typedef const IfcParse::declaration*& reference;
|
typedef const IfcParse::declaration*& reference;
|
||||||
typedef const IfcParse::declaration** pointer;
|
typedef const IfcParse::declaration** pointer;
|
||||||
typedef std::forward_iterator_tag iterator_category;
|
typedef std::forward_iterator_tag iterator_category;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct iterator_traits<IfcParse::IfcFile::type_iterator<IfcParse::IfcFile::entities_by_type_t::value_type::second_type>> {
|
||||||
|
typedef ptrdiff_t difference_type;
|
||||||
|
typedef IfcParse::IfcFile::entities_by_type_t::value_type value_type;
|
||||||
|
typedef IfcParse::IfcFile::entities_by_type_t::value_type reference;
|
||||||
|
typedef IfcParse::IfcFile::entities_by_type_t::value_type* pointer;
|
||||||
|
typedef std::forward_iterator_tag iterator_category;
|
||||||
|
};
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+80
-79
@@ -1555,7 +1555,7 @@ void IfcEntityInstanceData::setArgument(size_t i, Argument* a, IfcUtil::Argument
|
|||||||
if (it != this->file->internal_guid_map().end()) {
|
if (it != this->file->internal_guid_map().end()) {
|
||||||
Logger::Warning("Duplicate guid " + guid);
|
Logger::Warning("Duplicate guid " + guid);
|
||||||
}
|
}
|
||||||
this->file->internal_guid_map()[guid] = this->file->instance_by_id(this->id());
|
this->file->internal_guid_map()[guid] = this->file->instance_by_id_2(this->id());
|
||||||
} catch (IfcParse::IfcException& e) {
|
} catch (IfcParse::IfcException& e) {
|
||||||
Logger::Error(e);
|
Logger::Error(e);
|
||||||
}
|
}
|
||||||
@@ -1656,7 +1656,7 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
|
|||||||
boost::circular_buffer<Token> token_stream(3, Token());
|
boost::circular_buffer<Token> token_stream(3, Token());
|
||||||
|
|
||||||
IfcEntityInstanceData* data;
|
IfcEntityInstanceData* data;
|
||||||
IfcUtil::IfcBaseClass* instance = 0;
|
instance_storage_type instance = 0;
|
||||||
|
|
||||||
unsigned current_id = 0;
|
unsigned current_id = 0;
|
||||||
int progress = 0;
|
int progress = 0;
|
||||||
@@ -1682,7 +1682,7 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data = new IfcEntityInstanceData(entity_type, this, current_id, token_stream[2].startPos);
|
data = new IfcEntityInstanceData(entity_type, this, current_id, token_stream[2].startPos);
|
||||||
instance = schema()->instantiate(data);
|
instance = instance_storage_type(schema()->instantiate(data));
|
||||||
|
|
||||||
/// @todo Printing to stdout in a library class feels weird. Maybe move the progress prints to the client code?
|
/// @todo Printing to stdout in a library class feels weird. Maybe move the progress prints to the client code?
|
||||||
// Update the status after every 1000 instances parsed
|
// Update the status after every 1000 instances parsed
|
||||||
@@ -1715,22 +1715,10 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
|
|||||||
|
|
||||||
const IfcParse::declaration* ty = &instance->declaration();
|
const IfcParse::declaration* ty = &instance->declaration();
|
||||||
|
|
||||||
{
|
bytype_excl_.insert({ ty, instance });
|
||||||
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 (;;) {
|
for (;;) {
|
||||||
aggregate_of_instance::ptr insts = instances_by_type(ty);
|
bytype_.insert({ ty, instance });
|
||||||
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();
|
const IfcParse::declaration* pt = ty->as_entity()->supertype();
|
||||||
if (pt != nullptr) {
|
if (pt != nullptr) {
|
||||||
ty = pt;
|
ty = pt;
|
||||||
@@ -1898,7 +1886,7 @@ void IfcFile::addEntities(aggregate_of_instance::ptr entities) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id) {
|
IfcFile::instance_storage_type IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id) {
|
||||||
if (id != -1 && byid_.find((unsigned)id) != byid_.end()) {
|
if (id != -1 && byid_.find((unsigned)id) != byid_.end()) {
|
||||||
throw IfcParse::IfcException("An instance with id " + boost::lexical_cast<std::string>(id) + " is already part of this file");
|
throw IfcParse::IfcException("An instance with id " + boost::lexical_cast<std::string>(id) + " is already part of this file");
|
||||||
}
|
}
|
||||||
@@ -1914,7 +1902,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
|
|||||||
return mit->second;
|
return mit->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcUtil::IfcBaseClass* new_entity = entity;
|
instance_storage_type new_entity = instance_storage_type(entity);
|
||||||
|
|
||||||
// Obtain all forward references by a depth-first
|
// Obtain all forward references by a depth-first
|
||||||
// traversal and add them to the file.
|
// traversal and add them to the file.
|
||||||
@@ -1944,7 +1932,16 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
|
|||||||
|
|
||||||
// If it is part of this file
|
// If it is part of this file
|
||||||
// nothing else needs to be done.
|
// nothing else needs to be done.
|
||||||
return entity;
|
if constexpr (std::is_same_v<IfcFile::instance_storage_type, IfcUtil::IfcBaseClass*>) {
|
||||||
|
return entity;
|
||||||
|
} else {
|
||||||
|
for (auto& x : byid_) {
|
||||||
|
if (&*x.second == entity) {
|
||||||
|
return x.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw std::runtime_error("Internal error");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// An instance is being added from another file. A copy of the
|
// An instance is being added from another file. A copy of the
|
||||||
@@ -1952,7 +1949,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
|
|||||||
// need to be updated to point to instances in this file.
|
// need to be updated to point to instances in this file.
|
||||||
IfcFile* other_file = entity->data().file;
|
IfcFile* other_file = entity->data().file;
|
||||||
IfcEntityInstanceData* we = new IfcEntityInstanceData(entity->data());
|
IfcEntityInstanceData* we = new IfcEntityInstanceData(entity->data());
|
||||||
new_entity = schema()->instantiate(we);
|
new_entity = instance_storage_type(schema()->instantiate(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.
|
||||||
@@ -1981,7 +1978,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument();
|
IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument();
|
||||||
copy->set(eit->second);
|
copy->set(&*eit->second);
|
||||||
we->setArgument(i, copy);
|
we->setArgument(i, copy);
|
||||||
} else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
|
} else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
|
||||||
aggregate_of_instance::ptr instances = *attr;
|
aggregate_of_instance::ptr instances = *attr;
|
||||||
@@ -1991,7 +1988,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
|
|||||||
if (eit == entity_file_map_.end()) {
|
if (eit == entity_file_map_.end()) {
|
||||||
throw IfcParse::IfcException("Unable to map instance to file");
|
throw IfcParse::IfcException("Unable to map instance to file");
|
||||||
}
|
}
|
||||||
new_instances->push(eit->second);
|
new_instances->push(&*eit->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument();
|
IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument();
|
||||||
@@ -2007,7 +2004,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
|
|||||||
if (eit == entity_file_map_.end()) {
|
if (eit == entity_file_map_.end()) {
|
||||||
throw IfcParse::IfcException("Unable to map instance to file");
|
throw IfcParse::IfcException("Unable to map instance to file");
|
||||||
}
|
}
|
||||||
list.push_back(eit->second);
|
list.push_back(&*eit->second);
|
||||||
}
|
}
|
||||||
new_instances->push(list);
|
new_instances->push(list);
|
||||||
}
|
}
|
||||||
@@ -2076,7 +2073,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entity_file_map_.insert(entity_entity_map_t::value_type(entity->identity(), new_entity));
|
entity_file_map_.insert(entity_entity_map_t::value_type(entity->identity(), &*new_entity));
|
||||||
}
|
}
|
||||||
|
|
||||||
// For subtypes of IfcRoot, the GUID mapping needs to be updated.
|
// For subtypes of IfcRoot, the GUID mapping needs to be updated.
|
||||||
@@ -2098,21 +2095,11 @@ 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);
|
bytype_excl_.insert({ ty, new_entity });
|
||||||
if (!insts) {
|
|
||||||
insts = aggregate_of_instance::ptr(new aggregate_of_instance());
|
|
||||||
bytype_excl_[ty] = insts;
|
|
||||||
}
|
|
||||||
insts->push(new_entity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; ty->as_entity() != nullptr;) {
|
for (; ty->as_entity() != nullptr;) {
|
||||||
aggregate_of_instance::ptr insts = instances_by_type(ty);
|
bytype_.insert({ ty, new_entity });
|
||||||
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();
|
const IfcParse::declaration* pt = ty->as_entity()->supertype();
|
||||||
if (pt != nullptr) {
|
if (pt != nullptr) {
|
||||||
@@ -2158,7 +2145,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (parsing_complete_ && (ty->as_entity() != nullptr)) {
|
if (parsing_complete_ && (ty->as_entity() != nullptr)) {
|
||||||
build_inverses_(new_entity);
|
build_inverses_(&*new_entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new_entity;
|
return new_entity;
|
||||||
@@ -2323,20 +2310,24 @@ 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 instances_of_same_type = bytype_excl_.equal_range(ty);
|
||||||
instances_of_same_type->remove(entity);
|
for (auto it = instances_of_same_type.first; it != instances_of_same_type.second;) {
|
||||||
if (instances_of_same_type->size() == 0) {
|
if (&*it->second == entity) {
|
||||||
bytype_excl_.erase(ty);
|
it = bytype_excl_.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
aggregate_of_instance::ptr instances_of_same_type = instances_by_type(ty);
|
auto instances_of_same_type = bytype_.equal_range(ty);
|
||||||
if (instances_of_same_type) {
|
for (auto it = instances_of_same_type.first; it != instances_of_same_type.second;) {
|
||||||
instances_of_same_type->remove(entity);
|
if (&*it->second == entity) {
|
||||||
}
|
it = bytype_.erase(it);
|
||||||
if (instances_of_same_type->size() == 0) {
|
} else {
|
||||||
bytype_.erase(ty);
|
++it;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const IfcParse::declaration* pt = ty->as_entity()->supertype();
|
const IfcParse::declaration* pt = ty->as_entity()->supertype();
|
||||||
@@ -2350,14 +2341,16 @@ void IfcFile::process_deletion_() {
|
|||||||
// entity_file_map is in place to prevent duplicate definitions with usage of add().
|
// entity_file_map is in place to prevent duplicate definitions with usage of add().
|
||||||
// Upon deletion the pairs need to be erased.
|
// Upon deletion the pairs need to be erased.
|
||||||
for (auto it = entity_file_map_.begin(); it != entity_file_map_.end();) {
|
for (auto it = entity_file_map_.begin(); it != entity_file_map_.end();) {
|
||||||
if (it->second == entity) {
|
if (&*it->second == entity) {
|
||||||
it = entity_file_map_.erase(it);
|
it = entity_file_map_.erase(it);
|
||||||
} else {
|
} else {
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete entity;
|
if constexpr (std::is_same_v<IfcFile::instance_storage_type, IfcUtil::IfcBaseClass*>) {
|
||||||
|
delete entity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (batch_mode_) {
|
if (batch_mode_) {
|
||||||
@@ -2397,21 +2390,19 @@ void IfcFile::process_deletion_() {
|
|||||||
batch_deletion_ids_.clear();
|
batch_deletion_ids_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
aggregate_of_instance::ptr IfcFile::instances_by_type(const IfcParse::declaration* t) {
|
IfcFile::type_iterator_range_t IfcFile::instances_by_type(const IfcParse::declaration* t) {
|
||||||
entities_by_type_t::const_iterator it = bytype_.find(t);
|
return bytype_.equal_range(t);
|
||||||
return (it == bytype_.end()) ? aggregate_of_instance::ptr() : it->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aggregate_of_instance::ptr IfcFile::instances_by_type_excl_subtypes(const IfcParse::declaration* t) {
|
IfcFile::type_iterator_range_t IfcFile::instances_by_type_excl_subtypes(const IfcParse::declaration* t) {
|
||||||
entities_by_type_t::const_iterator it = bytype_excl_.find(t);
|
return bytype_.equal_range(t);
|
||||||
return (it == bytype_excl_.end()) ? aggregate_of_instance::ptr() : it->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aggregate_of_instance::ptr IfcFile::instances_by_type(const std::string& t) {
|
IfcFile::type_iterator_range_t IfcFile::instances_by_type(const std::string& t) {
|
||||||
return instances_by_type(schema()->declaration_by_name(t));
|
return instances_by_type(schema()->declaration_by_name(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
aggregate_of_instance::ptr IfcFile::instances_by_type_excl_subtypes(const std::string& t) {
|
IfcFile::type_iterator_range_t IfcFile::instances_by_type_excl_subtypes(const std::string& t) {
|
||||||
return instances_by_type_excl_subtypes(schema()->declaration_by_name(t));
|
return instances_by_type_excl_subtypes(schema()->declaration_by_name(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2424,6 +2415,14 @@ aggregate_of_instance::ptr IfcFile::instances_by_reference(int t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IfcUtil::IfcBaseClass* IfcFile::instance_by_id(int id) {
|
IfcUtil::IfcBaseClass* IfcFile::instance_by_id(int id) {
|
||||||
|
entity_by_id_t::const_iterator it = byid_.find(id);
|
||||||
|
if (it == byid_.end()) {
|
||||||
|
throw IfcException("Instance #" + boost::lexical_cast<std::string>(id) + " not found");
|
||||||
|
}
|
||||||
|
return &*it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
IfcFile::instance_storage_type IfcFile::instance_by_id_2(int id) {
|
||||||
entity_by_id_t::const_iterator it = byid_.find(id);
|
entity_by_id_t::const_iterator it = byid_.find(id);
|
||||||
if (it == byid_.end()) {
|
if (it == byid_.end()) {
|
||||||
throw IfcException("Instance #" + boost::lexical_cast<std::string>(id) + " not found");
|
throw IfcException("Instance #" + boost::lexical_cast<std::string>(id) + " not found");
|
||||||
@@ -2431,7 +2430,7 @@ IfcUtil::IfcBaseClass* IfcFile::instance_by_id(int id) {
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcUtil::IfcBaseClass* IfcFile::instance_by_guid(const std::string& guid) {
|
IfcFile::instance_storage_type IfcFile::instance_by_guid(const std::string& guid) {
|
||||||
entity_by_guid_t::const_iterator it = byguid_.find(guid);
|
entity_by_guid_t::const_iterator it = byguid_.find(guid);
|
||||||
if (it == byguid_.end()) {
|
if (it == byguid_.end()) {
|
||||||
throw IfcException("Instance with GlobalId '" + guid + "' not found");
|
throw IfcException("Instance with GlobalId '" + guid + "' not found");
|
||||||
@@ -2441,15 +2440,17 @@ IfcUtil::IfcBaseClass* IfcFile::instance_by_guid(const std::string& guid) {
|
|||||||
|
|
||||||
// FIXME: Test destructor to delete entity and arg allocations
|
// FIXME: Test destructor to delete entity and arg allocations
|
||||||
IfcFile::~IfcFile() {
|
IfcFile::~IfcFile() {
|
||||||
std::set<IfcUtil::IfcBaseClass*> entities_to_delete;
|
if constexpr (std::is_same_v<IfcFile::instance_storage_type, IfcUtil::IfcBaseClass*>) {
|
||||||
for (const auto& pair : byid_) {
|
std::set<IfcFile::instance_storage_type> entities_to_delete;
|
||||||
entities_to_delete.insert(pair.second);
|
for (const auto& pair : byid_) {
|
||||||
}
|
entities_to_delete.insert(pair.second);
|
||||||
for (const auto& pair : byidentity_) {
|
}
|
||||||
entities_to_delete.insert(pair.second);
|
for (const auto& pair : byidentity_) {
|
||||||
}
|
entities_to_delete.insert(pair.second);
|
||||||
for (auto* entity : entities_to_delete) {
|
}
|
||||||
delete entity;
|
for (auto entity : entities_to_delete) {
|
||||||
|
delete &*entity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
delete stream;
|
delete stream;
|
||||||
delete tokens;
|
delete tokens;
|
||||||
@@ -2463,19 +2464,19 @@ IfcFile::entity_by_id_t::const_iterator IfcFile::end() const {
|
|||||||
return byid_.end();
|
return byid_.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcFile::type_iterator IfcFile::types_begin() const {
|
IfcFile::type_iterator<IfcFile::entities_by_type_t::key_type> IfcFile::types_begin() const {
|
||||||
return bytype_excl_.begin();
|
return bytype_excl_.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcFile::type_iterator IfcFile::types_end() const {
|
IfcFile::type_iterator<IfcFile::entities_by_type_t::key_type> IfcFile::types_end() const {
|
||||||
return bytype_excl_.end();
|
return bytype_excl_.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcFile::type_iterator IfcFile::types_incl_super_begin() const {
|
IfcFile::type_iterator<IfcFile::entities_by_type_t::key_type> IfcFile::types_incl_super_begin() const {
|
||||||
return bytype_.begin();
|
return bytype_.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcFile::type_iterator IfcFile::types_incl_super_end() const {
|
IfcFile::type_iterator<IfcFile::entities_by_type_t::key_type> IfcFile::types_incl_super_end() const {
|
||||||
return bytype_.end();
|
return bytype_.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2490,12 +2491,12 @@ struct id_instance_pair_sorter {
|
|||||||
std::ostream& operator<<(std::ostream& out, const IfcParse::IfcFile& file) {
|
std::ostream& operator<<(std::ostream& out, const IfcParse::IfcFile& file) {
|
||||||
file.header().write(out);
|
file.header().write(out);
|
||||||
|
|
||||||
typedef std::vector<std::pair<unsigned int, IfcUtil::IfcBaseClass*>> vector_t;
|
typedef std::vector<std::pair<unsigned int, IfcParse::IfcFile::instance_storage_type>> vector_t;
|
||||||
vector_t sorted(file.begin(), file.end());
|
vector_t sorted(file.begin(), file.end());
|
||||||
std::sort(sorted.begin(), sorted.end(), id_instance_pair_sorter());
|
std::sort(sorted.begin(), sorted.end(), id_instance_pair_sorter());
|
||||||
|
|
||||||
for (vector_t::const_iterator it = sorted.begin(); it != sorted.end(); ++it) {
|
for (vector_t::const_iterator it = sorted.begin(); it != sorted.end(); ++it) {
|
||||||
const IfcUtil::IfcBaseClass* e = it->second;
|
auto& e = it->second;
|
||||||
if (e->declaration().as_entity() != nullptr) {
|
if (e->declaration().as_entity() != nullptr) {
|
||||||
out << e->data().toString(true) << ";" << std::endl;
|
out << e->data().toString(true) << ";" << std::endl;
|
||||||
}
|
}
|
||||||
@@ -2622,16 +2623,16 @@ void IfcFile::setDefaultHeaderValues() {
|
|||||||
std::pair<IfcUtil::IfcBaseClass*, double> IfcFile::getUnit(const std::string& unit_type) {
|
std::pair<IfcUtil::IfcBaseClass*, double> IfcFile::getUnit(const std::string& unit_type) {
|
||||||
std::pair<IfcUtil::IfcBaseClass*, double> return_value(0, 1.);
|
std::pair<IfcUtil::IfcBaseClass*, double> return_value(0, 1.);
|
||||||
|
|
||||||
aggregate_of_instance::ptr projects = instances_by_type(schema()->declaration_by_name("IfcProject"));
|
auto projects = instances_by_type(schema()->declaration_by_name("IfcProject"));
|
||||||
if (!projects || projects->size() == 0) {
|
if (std::distance(projects.first, projects.second) == 0) {
|
||||||
try {
|
try {
|
||||||
projects = instances_by_type(schema()->declaration_by_name("IfcContext"));
|
projects = instances_by_type(schema()->declaration_by_name("IfcContext"));
|
||||||
} catch (IfcException& e) {
|
} catch (IfcException& e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (projects && projects->size() == 1) {
|
if (std::distance(projects.first, projects.second) == 1) {
|
||||||
IfcUtil::IfcBaseClass* project = *projects->begin();
|
auto project = *projects.first;
|
||||||
|
|
||||||
IfcUtil::IfcBaseClass* unit_assignment = *project->data().getArgument(
|
IfcUtil::IfcBaseClass* unit_assignment = *project->data().getArgument(
|
||||||
project->declaration().as_entity()->attribute_index("UnitsInContext"));
|
project->declaration().as_entity()->attribute_index("UnitsInContext"));
|
||||||
@@ -2704,7 +2705,7 @@ void IfcParse::IfcFile::build_inverses_(IfcUtil::IfcBaseClass* inst) {
|
|||||||
|
|
||||||
void IfcParse::IfcFile::build_inverses() {
|
void IfcParse::IfcFile::build_inverses() {
|
||||||
for (const auto& pair : *this) {
|
for (const auto& pair : *this) {
|
||||||
build_inverses_(pair.second);
|
build_inverses_(&*pair.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -480,7 +480,7 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
|
|||||||
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
|
||||||
// subsequent child nodes
|
// subsequent child nodes
|
||||||
newinst = state->file->addEntity(newinst);
|
newinst = &*state->file->addEntity(newinst);
|
||||||
if (id) {
|
if (id) {
|
||||||
state->idmap[*id] = newinst->data().id();
|
state->idmap[*id] = newinst->data().id();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,10 +49,10 @@ private:
|
|||||||
%rename("by_id") instance_by_id;
|
%rename("by_id") instance_by_id;
|
||||||
%rename("by_type") instances_by_type;
|
%rename("by_type") instances_by_type;
|
||||||
%rename("by_type_excl_subtypes") instances_by_type_excl_subtypes;
|
%rename("by_type_excl_subtypes") instances_by_type_excl_subtypes;
|
||||||
%rename("entity_instance") IfcBaseClass;
|
|
||||||
%rename("file") IfcFile;
|
%rename("file") IfcFile;
|
||||||
%rename("add") addEntity;
|
%ignore IfcParse::IfcFile::addEntity;
|
||||||
%rename("remove") removeEntity;
|
%ignore IfcParse::IfcFile::removeEntity;
|
||||||
|
|
||||||
class attribute_value_derived {};
|
class attribute_value_derived {};
|
||||||
%{
|
%{
|
||||||
@@ -88,12 +88,71 @@ PyObject* get_feature(const std::string& x) {
|
|||||||
%}
|
%}
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
class entity_instance;
|
||||||
|
const std::string& helper_fn_declaration_get_name(const IfcParse::declaration* decl);
|
||||||
|
IfcUtil::ArgumentType helper_fn_attribute_type(const entity_instance* inst, unsigned i);
|
||||||
|
%}
|
||||||
|
|
||||||
static const std::string& helper_fn_declaration_get_name(const IfcParse::declaration* decl) {
|
|
||||||
|
%inline %{
|
||||||
|
class entity_instance {
|
||||||
|
boost::variant<
|
||||||
|
IfcParse::IfcFile::instance_storage_type,
|
||||||
|
std::weak_ptr<IfcUtil::IfcBaseClass>
|
||||||
|
> data_;
|
||||||
|
|
||||||
|
struct visitor {
|
||||||
|
IfcParse::IfcFile::instance_storage_type operator()(const IfcParse::IfcFile::instance_storage_type& t) {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
IfcParse::IfcFile::instance_storage_type operator()(const std::weak_ptr<IfcUtil::IfcBaseClass>& t) {
|
||||||
|
auto u = t.lock();
|
||||||
|
if (u) {
|
||||||
|
return u;
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("No longer availabe");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
entity_instance(const IfcParse::IfcFile::instance_storage_type& shared)
|
||||||
|
: data_(std::weak_ptr<IfcUtil::IfcBaseClass>(shared))
|
||||||
|
{}
|
||||||
|
|
||||||
|
entity_instance(IfcUtil::IfcBaseClass* naked)
|
||||||
|
: data_(IfcParse::IfcFile::instance_storage_type(naked))
|
||||||
|
{}
|
||||||
|
|
||||||
|
operator IfcUtil::IfcBaseClass*() const {
|
||||||
|
return &*boost::apply_visitor(visitor{}, data_);
|
||||||
|
}
|
||||||
|
|
||||||
|
const IfcParse::declaration& declaration() const {
|
||||||
|
return boost::apply_visitor(visitor{}, data_)->declaration();
|
||||||
|
}
|
||||||
|
|
||||||
|
const IfcEntityInstanceData& data() const {
|
||||||
|
return boost::apply_visitor(visitor{}, data_)->data();
|
||||||
|
}
|
||||||
|
|
||||||
|
IfcEntityInstanceData& data() {
|
||||||
|
return boost::apply_visitor(visitor{}, data_)->data();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t identity() const {
|
||||||
|
return boost::apply_visitor(visitor{}, data_)->identity();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
%{
|
||||||
|
|
||||||
|
const std::string& helper_fn_declaration_get_name(const IfcParse::declaration* decl) {
|
||||||
return decl->name();
|
return decl->name();
|
||||||
}
|
}
|
||||||
|
|
||||||
static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClass* inst, unsigned i) {
|
IfcUtil::ArgumentType helper_fn_attribute_type(const entity_instance* inst, unsigned i) {
|
||||||
const IfcParse::parameter_type* pt = 0;
|
const IfcParse::parameter_type* pt = 0;
|
||||||
if (inst->declaration().as_entity()) {
|
if (inst->declaration().as_entity()) {
|
||||||
pt = inst->declaration().as_entity()->attribute_by_index(i)->type_of_attribute();
|
pt = inst->declaration().as_entity()->attribute_by_index(i)->type_of_attribute();
|
||||||
@@ -122,20 +181,28 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
|
|||||||
return reinterpret_cast<size_t>($self);
|
return reinterpret_cast<size_t>($self);
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcUtil::IfcBaseClass* by_guid(const std::string& guid) {
|
entity_instance by_guid(const std::string& guid) {
|
||||||
return $self->instance_by_guid(guid);
|
return $self->instance_by_guid(guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity_instance add(entity_instance& e, int i) {
|
||||||
|
return $self->addEntity(e, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(entity_instance& e) {
|
||||||
|
return $self->removeEntity(e);
|
||||||
|
}
|
||||||
|
|
||||||
aggregate_of_instance::ptr get_inverse(IfcUtil::IfcBaseClass* e) {
|
aggregate_of_instance::ptr get_inverse(entity_instance& e) {
|
||||||
return $self->getInverse(e->data().id(), 0, -1);
|
return $self->getInverse(e.data().id(), 0, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> get_inverse_indices(IfcUtil::IfcBaseClass* e) {
|
std::vector<int> get_inverse_indices(entity_instance& e) {
|
||||||
return $self->get_inverse_indices(e->data().id());
|
return $self->get_inverse_indices(e.data().id());
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_total_inverses(IfcUtil::IfcBaseClass* e) {
|
int get_total_inverses(entity_instance& e) {
|
||||||
return $self->getTotalInverses(e->data().id());
|
return $self->getTotalInverses(e.data().id());
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(const std::string& fn) {
|
void write(const std::string& fn) {
|
||||||
@@ -186,7 +253,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
|
|||||||
%}
|
%}
|
||||||
}
|
}
|
||||||
|
|
||||||
%extend IfcUtil::IfcBaseClass {
|
%extend entity_instance {
|
||||||
|
|
||||||
int get_attribute_category(const std::string& name) const {
|
int get_attribute_category(const std::string& name) const {
|
||||||
if (!$self->declaration().as_entity()) {
|
if (!$self->declaration().as_entity()) {
|
||||||
@@ -288,7 +355,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
|
|||||||
return std::pair<IfcUtil::ArgumentType,Argument*>($self->data().getArgument(i)->type(), $self->data().getArgument(i));
|
return std::pair<IfcUtil::ArgumentType,Argument*>($self->data().getArgument(i)->type(), $self->data().getArgument(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool __eq__(IfcUtil::IfcBaseClass* other) const {
|
bool __eq__(entity_instance* other) const {
|
||||||
return $self->identity() == other->identity();
|
return $self->identity() == other->identity();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,7 +544,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setArgumentAsEntityInstance(unsigned int i, IfcUtil::IfcBaseClass* v) {
|
void setArgumentAsEntityInstance(unsigned int i, entity_instance* 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) {
|
||||||
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
|
IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument();
|
||||||
@@ -603,7 +670,7 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
|
|||||||
return IFCOPENSHELL_VERSION;
|
return IFCOPENSHELL_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcUtil::IfcBaseClass* new_IfcBaseClass(const std::string& schema_identifier, const std::string& name) {
|
entity_instance new_IfcBaseClass(const std::string& schema_identifier, const std::string& name) {
|
||||||
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 = new IfcEntityInstanceData(decl);
|
IfcEntityInstanceData* data = new IfcEntityInstanceData(decl);
|
||||||
|
|||||||
@@ -443,14 +443,14 @@ void GltfSerializer::setFile(IfcParse::IfcFile* f) {
|
|||||||
boost::optional<std::array<double, 3>> crs_x_axis;
|
boost::optional<std::array<double, 3>> crs_x_axis;
|
||||||
boost::optional<std::array<double, 3>> eastings_northings_elevation;
|
boost::optional<std::array<double, 3>> eastings_northings_elevation;
|
||||||
|
|
||||||
aggregate_of_instance::ptr coordops;
|
IfcParse::IfcFile::type_iterator_range_t coordops;
|
||||||
try {
|
try {
|
||||||
coordops = f->instances_by_type("IfcCoordinateOperation");
|
coordops = f->instances_by_type("IfcCoordinateOperation");
|
||||||
} catch (IfcParse::IfcException&) {
|
} catch (IfcParse::IfcException&) {
|
||||||
// Ignored. Schema likely doesn't support IfcCoordinateOperation.
|
// Ignored. Schema likely doesn't support IfcCoordinateOperation.
|
||||||
}
|
}
|
||||||
if (coordops) {
|
if (std::distance(coordops.first, coordops.second)) {
|
||||||
for (auto& coordop : *coordops) {
|
for (auto& coordop : boost::make_iterator_range(coordops)) {
|
||||||
IfcUtil::IfcBaseClass* source_crs = *coordop->as<IfcUtil::IfcBaseEntity>()->get("SourceCRS");
|
IfcUtil::IfcBaseClass* source_crs = *coordop->as<IfcUtil::IfcBaseEntity>()->get("SourceCRS");
|
||||||
if (source_crs->declaration().is("IfcGeometricRepresentationContext")) {
|
if (source_crs->declaration().is("IfcGeometricRepresentationContext")) {
|
||||||
IfcUtil::IfcBaseClass* target_crs = *coordop->as<IfcUtil::IfcBaseEntity>()->get("TargetCRS");
|
IfcUtil::IfcBaseClass* target_crs = *coordop->as<IfcUtil::IfcBaseEntity>()->get("TargetCRS");
|
||||||
@@ -486,9 +486,9 @@ void GltfSerializer::setFile(IfcParse::IfcFile* f) {
|
|||||||
if (!crs_epsg) {
|
if (!crs_epsg) {
|
||||||
auto sites = f->instances_by_type("IfcSite");
|
auto sites = f->instances_by_type("IfcSite");
|
||||||
|
|
||||||
if (sites && sites->size() == 1) {
|
if (std::distance(sites.first, sites.second)) {
|
||||||
auto lat_attr = (*sites->begin())->as<IfcUtil::IfcBaseEntity>()->get("RefLatitude");
|
auto lat_attr = (*sites.first)->as<IfcUtil::IfcBaseEntity>()->get("RefLatitude");
|
||||||
auto lon_attr = (*sites->begin())->as<IfcUtil::IfcBaseEntity>()->get("RefLongitude");
|
auto lon_attr = (*sites.first)->as<IfcUtil::IfcBaseEntity>()->get("RefLongitude");
|
||||||
|
|
||||||
if (!lat_attr->isNull() && !lon_attr->isNull()) {
|
if (!lat_attr->isNull() && !lon_attr->isNull()) {
|
||||||
std::vector<int> lat_dms = *lat_attr;
|
std::vector<int> lat_dms = *lat_attr;
|
||||||
@@ -521,8 +521,8 @@ void GltfSerializer::setFile(IfcParse::IfcFile* f) {
|
|||||||
|
|
||||||
auto contexts = f->instances_by_type_excl_subtypes("IfcGeometricRepresentationContext");
|
auto contexts = f->instances_by_type_excl_subtypes("IfcGeometricRepresentationContext");
|
||||||
|
|
||||||
if (contexts && contexts->size() > 0) {
|
if (std::distance(contexts.first, contexts.second)) {
|
||||||
auto context = (*contexts->begin())->as<IfcUtil::IfcBaseEntity>();
|
auto context = (*contexts.first)->as<IfcUtil::IfcBaseEntity>();
|
||||||
auto north_attr = context->get("TrueNorth");
|
auto north_attr = context->get("TrueNorth");
|
||||||
if (!north_attr->isNull()) {
|
if (!north_attr->isNull()) {
|
||||||
IfcUtil::IfcBaseClass* north = *north_attr;
|
IfcUtil::IfcBaseClass* north = *north_attr;
|
||||||
|
|||||||
@@ -1830,13 +1830,13 @@ void SvgSerializer::addTextAnnotations(const drawing_key& k) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aggregate_of_instance::ptr annotations;
|
boost::optional<IfcParse::IfcFile::type_iterator_range_t> annotations;
|
||||||
if (file) {
|
if (file) {
|
||||||
annotations = file->instances_by_type("IfcAnnotation");
|
annotations = file->instances_by_type("IfcAnnotation");
|
||||||
}
|
}
|
||||||
if (annotations) {
|
if (annotations) {
|
||||||
for (auto& ann_ : *annotations) {
|
for (auto& ann_ : boost::make_iterator_range(*annotations)) {
|
||||||
auto ann = (IfcUtil::IfcBaseEntity*) ann_;
|
auto ann = ann_->as<IfcUtil::IfcBaseEntity>();
|
||||||
|
|
||||||
auto ot = ann->get("ObjectType");
|
auto ot = ann->get("ObjectType");
|
||||||
auto nm = ann->get("Name");
|
auto nm = ann->get("Name");
|
||||||
@@ -2072,50 +2072,48 @@ void SvgSerializer::finalize() {
|
|||||||
|
|
||||||
if (file && storey_height_display_ != SH_NONE && pln && std::abs(pln->Position().Direction().Z()) < 1.e-5) {
|
if (file && storey_height_display_ != SH_NONE && pln && std::abs(pln->Position().Direction().Z()) < 1.e-5) {
|
||||||
auto storeys = file->instances_by_type("IfcBuildingStorey");
|
auto storeys = file->instances_by_type("IfcBuildingStorey");
|
||||||
if (storeys) {
|
const double lu = file->getUnit("LENGTHUNIT").second;
|
||||||
const double lu = file->getUnit("LENGTHUNIT").second;
|
for (auto& s : boost::make_iterator_range(storeys)) {
|
||||||
for (auto& s : *storeys) {
|
auto storey = s->as<IfcUtil::IfcBaseEntity>();
|
||||||
auto storey = (IfcUtil::IfcBaseEntity*) s;
|
auto a = storey->get("Elevation");
|
||||||
auto a = storey->get("Elevation");
|
if (!a->isNull()) {
|
||||||
if (!a->isNull()) {
|
double elev = *a;
|
||||||
double elev = *a;
|
elev *= lu;
|
||||||
elev *= lu;
|
auto svg_name = nameElement(storey);
|
||||||
auto svg_name = nameElement(storey);
|
|
||||||
|
|
||||||
gp_Pln elev_pln(gp_Ax3(gp_Pnt(0, 0, elev), gp::DZ(), gp::DX()));
|
gp_Pln elev_pln(gp_Ax3(gp_Pnt(0, 0, elev), gp::DZ(), gp::DX()));
|
||||||
//, pln->Position().XDirection()));
|
//, pln->Position().XDirection()));
|
||||||
// auto ref_y = pln->Position().YDirection().XYZ().Dot(pln->Position().Location().XYZ());
|
// auto ref_y = pln->Position().YDirection().XYZ().Dot(pln->Position().Location().XYZ());
|
||||||
|
|
||||||
double x0, y0, z0, x1, y1, z1;
|
double x0, y0, z0, x1, y1, z1;
|
||||||
bnd_.Get(x0, y0, z0, x1, y1, z1);
|
bnd_.Get(x0, y0, z0, x1, y1, z1);
|
||||||
|
|
||||||
// @todo this is a hack in order to get the auto elevations (which are 0.1 offset from
|
// @todo this is a hack in order to get the auto elevations (which are 0.1 offset from
|
||||||
// the global bounding box) to include the storey height symbols.
|
// the global bounding box) to include the storey height symbols.
|
||||||
x0 -= 0.2;
|
x0 -= 0.2;
|
||||||
y0 -= 0.2;
|
y0 -= 0.2;
|
||||||
z0 -= 0.2;
|
z0 -= 0.2;
|
||||||
|
|
||||||
x1 += 0.2;
|
x1 += 0.2;
|
||||||
y1 += 0.2;
|
y1 += 0.2;
|
||||||
z1 += 0.2;
|
z1 += 0.2;
|
||||||
|
|
||||||
const double shll = storey_height_line_length_.get_value_or(2.);
|
const double shll = storey_height_line_length_.get_value_or(2.);
|
||||||
|
|
||||||
BRepBuilderAPI_MakeFace mf(elev_pln, x0 - shll, x1 + shll, y0 - shll, y1 + shll);
|
BRepBuilderAPI_MakeFace mf(elev_pln, x0 - shll, x1 + shll, y0 - shll, y1 + shll);
|
||||||
gp_Trsf trsf;
|
gp_Trsf trsf;
|
||||||
TopoDS_Compound C;
|
TopoDS_Compound C;
|
||||||
BRep_Builder B;
|
BRep_Builder B;
|
||||||
B.MakeCompound(C);
|
B.MakeCompound(C);
|
||||||
B.Add(C, mf.Face());
|
B.Add(C, mf.Face());
|
||||||
std::string name;
|
std::string name;
|
||||||
auto a2 = storey->get("Name");
|
auto a2 = storey->get("Name");
|
||||||
if (!a2->isNull()) {
|
if (!a2->isNull()) {
|
||||||
name = (std::string) *a2;
|
name = (std::string) *a2;
|
||||||
}
|
|
||||||
write(geometry_data{
|
|
||||||
C,{boost::none},trsf,storey,storey,elev,name,nameElement(storey)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
write(geometry_data{
|
||||||
|
C,{boost::none},trsf,storey,storey,elev,name,nameElement(storey)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2303,30 +2301,28 @@ void SvgSerializer::setFile(IfcParse::IfcFile* f) {
|
|||||||
file = f;
|
file = f;
|
||||||
|
|
||||||
auto storeys = f->instances_by_type("IfcBuildingStorey");
|
auto storeys = f->instances_by_type("IfcBuildingStorey");
|
||||||
if (!storeys || storeys->size() == 0) {
|
if (std::distance(storeys.first, storeys.second)) {
|
||||||
auto mapping = ifcopenshell::geometry::impl::mapping_implementations().construct(file, geometry_settings_);
|
auto mapping = ifcopenshell::geometry::impl::mapping_implementations().construct(file, geometry_settings_);
|
||||||
|
|
||||||
std::vector<const IfcParse::declaration*> to_derive_from;
|
std::vector<const IfcParse::declaration*> to_derive_from;
|
||||||
to_derive_from.push_back(f->schema()->declaration_by_name("IfcBuilding"));
|
to_derive_from.push_back(f->schema()->declaration_by_name("IfcBuilding"));
|
||||||
to_derive_from.push_back(f->schema()->declaration_by_name("IfcSite"));
|
to_derive_from.push_back(f->schema()->declaration_by_name("IfcSite"));
|
||||||
for (auto it = to_derive_from.begin(); it != to_derive_from.end(); ++it) {
|
for (auto it = to_derive_from.begin(); it != to_derive_from.end(); ++it) {
|
||||||
aggregate_of_instance::ptr insts = f->instances_by_type(*it);
|
auto insts = f->instances_by_type(*it);
|
||||||
if (insts) {
|
for (auto& product_ : boost::make_iterator_range(insts)) {
|
||||||
for (auto jt = insts->begin(); jt != insts->end(); ++jt) {
|
IfcUtil::IfcBaseEntity* product = product_->as<IfcUtil::IfcBaseEntity>();
|
||||||
IfcUtil::IfcBaseEntity* product = (IfcUtil::IfcBaseEntity*) *jt;
|
if (!product->get("ObjectPlacement")->isNull()) {
|
||||||
if (!product->get("ObjectPlacement")->isNull()) {
|
auto item = mapping->map(*product->get("ObjectPlacement"));
|
||||||
auto item = mapping->map(*product->get("ObjectPlacement"));
|
auto matrix = ifcopenshell::geometry::taxonomy::cast<ifcopenshell::geometry::taxonomy::matrix4>(item);
|
||||||
auto matrix = ifcopenshell::geometry::taxonomy::cast<ifcopenshell::geometry::taxonomy::matrix4>(item);
|
gp_Trsf trsf;
|
||||||
gp_Trsf trsf;
|
if (matrix) {
|
||||||
if (matrix) {
|
// @todo shouldn't this take into account configurable section height?
|
||||||
// @todo shouldn't this take into account configurable section height?
|
setSectionHeight(matrix->translation_part()(3) + 1.);
|
||||||
setSectionHeight(matrix->translation_part()(3) + 1.);
|
|
||||||
#ifdef TAXONOMY_USE_NAKED_PTR
|
#ifdef TAXONOMY_USE_NAKED_PTR
|
||||||
delete matrix;
|
delete matrix;
|
||||||
#endif
|
#endif
|
||||||
Logger::Warning("No building storeys encountered, used for reference:", product);
|
Logger::Warning("No building storeys encountered, used for reference:", product);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2352,9 +2348,9 @@ void SvgSerializer::setSectionHeightsFromStoreys(double offset) {
|
|||||||
section_data_.emplace();
|
section_data_.emplace();
|
||||||
auto storeys = file->instances_by_type("IfcBuildingStorey");
|
auto storeys = file->instances_by_type("IfcBuildingStorey");
|
||||||
const double lu = file->getUnit("LENGTHUNIT").second;
|
const double lu = file->getUnit("LENGTHUNIT").second;
|
||||||
if (storeys && storeys->size() > 0) {
|
if (std::distance(storeys.first, storeys.second)) {
|
||||||
for (auto& s : *storeys) {
|
for (auto& s : boost::make_iterator_range(storeys)) {
|
||||||
auto attr_value = ((IfcUtil::IfcBaseEntity*)s)->get("Elevation");
|
auto attr_value = s->as<IfcUtil::IfcBaseEntity>()->get("Elevation");
|
||||||
if (!attr_value->isNull()) {
|
if (!attr_value->isNull()) {
|
||||||
double elev;
|
double elev;
|
||||||
try {
|
try {
|
||||||
@@ -2366,7 +2362,7 @@ void SvgSerializer::setSectionHeightsFromStoreys(double offset) {
|
|||||||
if (!section_data_->empty()) {
|
if (!section_data_->empty()) {
|
||||||
boost::get<horizontal_plan>(section_data_->back()).next_elevation = elev * lu;
|
boost::get<horizontal_plan>(section_data_->back()).next_elevation = elev * lu;
|
||||||
}
|
}
|
||||||
section_data_->push_back(horizontal_plan{ (IfcUtil::IfcBaseEntity*)s, elev * lu, offset, std::numeric_limits<double>::infinity() });
|
section_data_->push_back(horizontal_plan{ s->as<IfcUtil::IfcBaseEntity>(), elev * lu, offset, std::numeric_limits<double>::infinity() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user