mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-19 03:33:48 +00:00
Work on runtime representation of schema
This commit is contained in:
+2951
-1191
File diff suppressed because it is too large
Load Diff
+7860
-6785
File diff suppressed because it is too large
Load Diff
+836
-5102
File diff suppressed because it is too large
Load Diff
@@ -41,6 +41,8 @@ public:
|
||||
private:
|
||||
typedef std::map<IfcUtil::IfcBaseClass*, IfcUtil::IfcBaseClass*> entity_entity_map_t;
|
||||
|
||||
const schema_definition* schema_;
|
||||
|
||||
bool _create_latebound_entities;
|
||||
|
||||
entity_by_id_t byid;
|
||||
@@ -131,6 +133,8 @@ public:
|
||||
bool create_latebound_entities() const { return _create_latebound_entities; }
|
||||
|
||||
std::pair<IfcSchema::IfcNamedUnit*, double> getUnit(IfcSchema::IfcUnitEnum::IfcUnitEnum);
|
||||
|
||||
const schema_definition* schema() const { return schema_; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ IfcSchema::IfcProject* IfcHierarchyHelper::addProject(IfcSchema::IfcOwnerHistory
|
||||
|
||||
void IfcHierarchyHelper::relatePlacements(IfcSchema::IfcProduct* parent, IfcSchema::IfcProduct* product) {
|
||||
IfcSchema::IfcObjectPlacement* place = product->hasObjectPlacement() ? product->ObjectPlacement() : 0;
|
||||
if (place && place->is(IfcSchema::Type::IfcLocalPlacement)) {
|
||||
if (place && place->declaration().is(IfcSchema::Type::IfcLocalPlacement)) {
|
||||
IfcSchema::IfcLocalPlacement* local_place = (IfcSchema::IfcLocalPlacement*) place;
|
||||
if (parent->hasObjectPlacement()) {
|
||||
local_place->setPlacementRelTo(parent->ObjectPlacement());
|
||||
|
||||
@@ -36,10 +36,10 @@ using namespace IfcUtil;
|
||||
|
||||
IfcWrite::IfcWritableEntity* IfcParse::IfcLateBoundEntity::writable_entity() {
|
||||
IfcWrite::IfcWritableEntity* e;
|
||||
if (entity->isWritable()) {
|
||||
e = (IfcWrite::IfcWritableEntity*) entity;
|
||||
if (data_->isWritable()) {
|
||||
e = (IfcWrite::IfcWritableEntity*) data_;
|
||||
} else {
|
||||
entity = e = new IfcWrite::IfcWritableEntity(entity);
|
||||
data_ = e = new IfcWrite::IfcWritableEntity(data_);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
@@ -47,20 +47,25 @@ IfcParse::IfcLateBoundEntity::IfcLateBoundEntity(const std::string& s) {
|
||||
std::string S = s;
|
||||
for (std::string::iterator i = S.begin(); i != S.end(); ++i ) *i = toupper(*i);
|
||||
_type = IfcSchema::Type::FromString(S);
|
||||
entity = new IfcWrite::IfcWritableEntity(_type);
|
||||
data_ = new IfcWrite::IfcWritableEntity(_type);
|
||||
for (unsigned i = 0; i < getArgumentCount(); ++i) {
|
||||
// Side effect of this is that a NULL attribute is created.
|
||||
entity->getArgument(i);
|
||||
data_->getArgument(i);
|
||||
}
|
||||
IfcSchema::Type::PopulateDerivedFields(writable_entity());
|
||||
}
|
||||
IfcParse::IfcLateBoundEntity::IfcLateBoundEntity(IfcAbstractEntity* e) {
|
||||
entity = e;
|
||||
data_ = e;
|
||||
_type = e->type();
|
||||
}
|
||||
/*
|
||||
const IfcParse::entity& IfcParse::IfcLateBoundEntity::entity() {
|
||||
return *get_schema().declaration_by_name(IfcSchema::Type::ToString(_type));
|
||||
}
|
||||
*/
|
||||
unsigned int IfcParse::IfcLateBoundEntity::id() const {
|
||||
if (entity->file) {
|
||||
return static_cast<unsigned int>(entity->id());
|
||||
if (data_->file) {
|
||||
return static_cast<unsigned int>(data_->id());
|
||||
} else {
|
||||
throw IfcException("Entity not bound to a file");
|
||||
}
|
||||
@@ -97,7 +102,7 @@ IfcSchema::Type::Enum IfcParse::IfcLateBoundEntity::getArgumentEntity(unsigned i
|
||||
return IfcSchema::Type::GetAttributeEntity(_type, i);
|
||||
}
|
||||
Argument* IfcParse::IfcLateBoundEntity::getArgument(unsigned int i) const {
|
||||
return entity->getArgument(i);
|
||||
return data_->getArgument(i);
|
||||
}
|
||||
const char* IfcParse::IfcLateBoundEntity::getArgumentName(unsigned int i) const {
|
||||
return IfcSchema::Type::GetAttributeName(_type,i).c_str();
|
||||
@@ -215,11 +220,11 @@ unsigned IfcParse::IfcLateBoundEntity::getArgumentIndex(const std::string& a) co
|
||||
return IfcSchema::Type::GetAttributeIndex(_type,a);
|
||||
}
|
||||
std::string IfcParse::IfcLateBoundEntity::toString() {
|
||||
return entity->toString(false);
|
||||
return data_->toString(false);
|
||||
}
|
||||
IfcEntityList::ptr IfcParse::IfcLateBoundEntity::get_inverse(const std::string& a) {
|
||||
std::pair<IfcSchema::Type::Enum, unsigned> inv = IfcSchema::Type::GetInverseAttribute(_type, a);
|
||||
return entity->getInverse(inv.first, inv.second);
|
||||
return data_->getInverse(inv.first, inv.second);
|
||||
}
|
||||
bool IfcParse::IfcLateBoundEntity::is_valid() {
|
||||
const unsigned arg_count = getArgumentCount();
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace IfcParse {
|
||||
// that in the IfcFile class the distinction what entity type to be created is
|
||||
// no longer necessary and weird diagonal casts when creating geometry from
|
||||
// IfcLateBoundEntities are eliminated.
|
||||
class IfcLateBoundEntity : public IfcUtil::IfcBaseEntity {
|
||||
class IfcLateBoundEntity : public IfcUtil::IfcBaseClass { // TODO: -Entity or -Type?
|
||||
private:
|
||||
IfcSchema::Type::Enum _type;
|
||||
IfcWrite::IfcWritableEntity* writable_entity();
|
||||
@@ -79,6 +79,20 @@ namespace IfcParse {
|
||||
std::string toString();
|
||||
|
||||
bool is_valid();
|
||||
|
||||
// const IfcParse::entity& entity();
|
||||
|
||||
const IfcAbstractEntity& data() const { return *data_; }
|
||||
IfcAbstractEntity& data() { return *data_; }
|
||||
|
||||
virtual const IfcParse::declaration& declaration() const {
|
||||
if (data().file) {
|
||||
throw;
|
||||
// data().file->
|
||||
} else {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+117
-98
@@ -37,6 +37,7 @@
|
||||
#include "../ifcparse/IfcLateBoundEntity.h"
|
||||
#include "../ifcparse/IfcFile.h"
|
||||
#include "../ifcparse/IfcSIPrefix.h"
|
||||
#include "../ifcparse/IfcSchema.h"
|
||||
|
||||
using namespace IfcParse;
|
||||
|
||||
@@ -764,7 +765,7 @@ EntityArgument::operator IfcEntityListList::ptr() const { throw IfcException("Ar
|
||||
unsigned int EntityArgument::size() const { return 1; }
|
||||
Argument* EntityArgument::operator [] (unsigned int i) const { throw IfcException("Argument is not a list of arguments"); }
|
||||
std::string EntityArgument::toString(bool upper) const {
|
||||
return entity->entity->toString(upper);
|
||||
return entity->data().toString(upper);
|
||||
}
|
||||
//return entity->entity->toString(); }
|
||||
bool EntityArgument::isNull() const { return false; }
|
||||
@@ -879,11 +880,10 @@ IfcEntityList::ptr Entity::getInverse(IfcSchema::Type::Enum type, int attribute_
|
||||
}
|
||||
|
||||
bool Entity::is(IfcSchema::Type::Enum v) const { return _type == v; }
|
||||
unsigned int Entity::id() { return _id; }
|
||||
unsigned int Entity::id() const { return _id; }
|
||||
|
||||
IfcWrite::IfcWritableEntity* Entity::isWritable() {
|
||||
return 0;
|
||||
}
|
||||
const IfcWrite::IfcWritableEntity* Entity::isWritable() const { return 0; }
|
||||
IfcWrite::IfcWritableEntity* Entity::isWritable() { return 0; }
|
||||
|
||||
IfcFile::IfcFile(bool create_latebound_entities)
|
||||
: _create_latebound_entities(create_latebound_entities)
|
||||
@@ -892,6 +892,9 @@ IfcFile::IfcFile(bool create_latebound_entities)
|
||||
, tokens(0)
|
||||
, MaxId(0)
|
||||
{
|
||||
if (!create_latebound_entities) {
|
||||
schema_ = &get_schema();
|
||||
}
|
||||
setDefaultHeaderValues();
|
||||
}
|
||||
|
||||
@@ -961,7 +964,7 @@ bool IfcFile::Init(IfcParse::IfcSpfStream* s) {
|
||||
std::stringstream ss; ss << "\r#" << currentId;
|
||||
Logger::Status(ss.str(), false);
|
||||
}
|
||||
if ( entity->is(IfcSchema::Type::IfcRoot) ) {
|
||||
if ( entity->declaration().is(IfcSchema::Type::IfcRoot) ) {
|
||||
IfcSchema::IfcRoot* ifc_root = (IfcSchema::IfcRoot*) entity;
|
||||
try {
|
||||
const std::string guid = ifc_root->GlobalId();
|
||||
@@ -976,7 +979,7 @@ bool IfcFile::Init(IfcParse::IfcSpfStream* s) {
|
||||
}
|
||||
}
|
||||
|
||||
IfcSchema::Type::Enum ty = entity->type();
|
||||
IfcSchema::Type::Enum ty = entity->declaration().type();
|
||||
do {
|
||||
IfcEntityList::ptr instances_by_type = entitiesByType(ty);
|
||||
if (!instances_by_type) {
|
||||
@@ -1031,8 +1034,9 @@ void IfcFile::traverse(IfcUtil::IfcBaseClass* instance, std::set<IfcUtil::IfcBas
|
||||
|
||||
if (level >= max_level && max_level > 0) return;
|
||||
|
||||
for (unsigned i = 0; i < instance->getArgumentCount(); ++i) {
|
||||
Argument* arg = instance->getArgument(i);
|
||||
auto attributes = instance->declaration().as_entity()->all_attributes();
|
||||
for (unsigned i = 0; i < attributes.size(); ++i) {
|
||||
Argument* arg = instance->data().getArgument(i);
|
||||
|
||||
if (arg->type() == IfcUtil::Argument_ENTITY_INSTANCE) {
|
||||
traverse(*arg, visited, list, level + 1, max_level);
|
||||
@@ -1065,10 +1069,10 @@ void IfcFile::addEntities(IfcEntityList::ptr es) {
|
||||
}
|
||||
}
|
||||
|
||||
IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* instance) {
|
||||
// If this instance has been inserted before, return
|
||||
// a reference to the copy that was created from it.
|
||||
entity_entity_map_t::iterator it = entity_file_map.find(entity);
|
||||
entity_entity_map_t::iterator it = entity_file_map.find(instance);
|
||||
if (it != entity_file_map.end()) {
|
||||
return it->second;
|
||||
}
|
||||
@@ -1076,39 +1080,44 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
// Obtain all forward references by a depth-first
|
||||
// traversal and add them to the file.
|
||||
try {
|
||||
IfcEntityList::ptr entity_attributes = traverse(entity, 1);
|
||||
IfcEntityList::ptr entity_attributes = traverse(instance, 1);
|
||||
for (IfcEntityList::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) {
|
||||
if (*it != entity) {
|
||||
if (*it != instance) {
|
||||
entity_file_map.insert(entity_entity_map_t::value_type(*it, addEntity(*it)));
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Failed to visit forward references of", entity->entity);
|
||||
Logger::Message(Logger::LOG_ERROR, "Failed to visit forward references of", instance);
|
||||
}
|
||||
|
||||
// See whether the instance is already part of a file
|
||||
if (entity->entity->file != 0) {
|
||||
if (entity->entity->file == this) {
|
||||
if (instance->data().file != 0) {
|
||||
if (instance->data().file == this) {
|
||||
// If it is part of this file
|
||||
// nothing needs to be done.
|
||||
return entity;
|
||||
return instance;
|
||||
}
|
||||
|
||||
// An instance is being added from another file. A copy of the
|
||||
// container and entity is created. The attribute references
|
||||
// container and instance is created. The attribute references
|
||||
// need to be updated to point to instances in this file.
|
||||
IfcFile* other_file = entity->entity->file;
|
||||
IfcWrite::IfcWritableEntity* we = new IfcWrite::IfcWritableEntity(entity->entity);
|
||||
IfcFile* other_file = instance->data().file;
|
||||
|
||||
// TODO: Proper copy constructor
|
||||
IfcWrite::IfcWritableEntity* we = new IfcWrite::IfcWritableEntity(&instance->data());
|
||||
|
||||
if (this->create_latebound_entities()) {
|
||||
entity = new IfcLateBoundEntity(we);
|
||||
instance = new IfcLateBoundEntity(we);
|
||||
} else {
|
||||
entity = IfcSchema::SchemaEntity(we);
|
||||
instance = IfcSchema::SchemaEntity(we);
|
||||
}
|
||||
|
||||
// In case an entity is added that contains geometry, the unit
|
||||
// In case an instance is added that contains geometry, the unit
|
||||
// information needs to be accounted for for IfcLengthMeasures.
|
||||
boost::optional<double> conversion_factor;
|
||||
|
||||
const schema_definition* s = schema();
|
||||
|
||||
for (unsigned i = 0; i < we->getArgumentCount(); ++i) {
|
||||
Argument* attr = we->getArgument(i);
|
||||
IfcUtil::ArgumentType attr_type = attr->type();
|
||||
@@ -1138,23 +1147,31 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
new_instances->push(list);
|
||||
}
|
||||
we->setArgument(i, new_instances);
|
||||
} else if (entity->getArgumentEntity(i) == IfcSchema::Type::IfcLengthMeasure ||
|
||||
entity->getArgumentEntity(i) == IfcSchema::Type::IfcPositiveLengthMeasure)
|
||||
{
|
||||
if (!conversion_factor) {
|
||||
conversion_factor = other_file->getUnit(IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT).second /
|
||||
getUnit(IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT).second;
|
||||
}
|
||||
if (attr_type == IfcUtil::Argument_DOUBLE) {
|
||||
double v = *attr;
|
||||
v *= *conversion_factor;
|
||||
we->setArgument(i, v);
|
||||
} else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) {
|
||||
std::vector<double> v = *attr;
|
||||
for (std::vector<double>::iterator it = v.begin(); it != v.end(); ++it) {
|
||||
(*it) *= *conversion_factor;
|
||||
} else if (s) {
|
||||
const entity* e = instance->declaration().as_entity();
|
||||
if (e) {
|
||||
const std::vector<const entity::attribute*> attrs = e->all_attributes();
|
||||
const parameter_type* pt = attrs[i]->type_of_attribute();
|
||||
while (pt->as_aggregation_type()) {
|
||||
pt = pt->as_aggregation_type()->type_of_element();
|
||||
}
|
||||
if (pt->is(IfcSchema::Type::IfcLengthMeasure)) {
|
||||
if (!conversion_factor) {
|
||||
conversion_factor = other_file->getUnit(IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT).second /
|
||||
getUnit(IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT).second;
|
||||
}
|
||||
if (attr_type == IfcUtil::Argument_DOUBLE) {
|
||||
double v = *attr;
|
||||
v *= *conversion_factor;
|
||||
we->setArgument(i, v);
|
||||
} else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) {
|
||||
std::vector<double> v = *attr;
|
||||
for (std::vector<double>::iterator it = v.begin(); it != v.end(); ++it) {
|
||||
(*it) *= *conversion_factor;
|
||||
}
|
||||
we->setArgument(i, v);
|
||||
}
|
||||
}
|
||||
we->setArgument(i, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1166,13 +1183,13 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
}
|
||||
|
||||
// For subtypes of IfcRoot, the GUID mapping needs to be updated.
|
||||
if (entity->is(IfcSchema::Type::IfcRoot)) {
|
||||
IfcSchema::IfcRoot* ifc_root = (IfcSchema::IfcRoot*) entity;
|
||||
if (instance->declaration().is(IfcSchema::Type::IfcRoot)) {
|
||||
IfcSchema::IfcRoot* ifc_root = (IfcSchema::IfcRoot*) instance;
|
||||
try {
|
||||
const std::string guid = ifc_root->GlobalId();
|
||||
if ( byguid.find(guid) != byguid.end() ) {
|
||||
std::stringstream ss;
|
||||
ss << "Overwriting entity with guid " << guid;
|
||||
ss << "Overwriting instance with guid " << guid;
|
||||
Logger::Message(Logger::LOG_WARNING,ss.str());
|
||||
}
|
||||
byguid[guid] = ifc_root;
|
||||
@@ -1181,74 +1198,75 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
}
|
||||
}
|
||||
|
||||
// The mapping by entity type is updated.
|
||||
IfcSchema::Type::Enum ty = entity->type();
|
||||
// The mapping by instance type is updated.
|
||||
IfcSchema::Type::Enum ty = instance->declaration().type();
|
||||
do {
|
||||
IfcEntityList::ptr instances_by_type = entitiesByType(ty);
|
||||
if (!instances_by_type) {
|
||||
instances_by_type = IfcEntityList::ptr(new IfcEntityList());
|
||||
bytype[ty] = instances_by_type;
|
||||
}
|
||||
instances_by_type->push(entity);
|
||||
instances_by_type->push(instance);
|
||||
ty = IfcSchema::Type::Parent(ty);
|
||||
} while ( ty > -1 );
|
||||
|
||||
int new_id = -1;
|
||||
if (entity->entity->isWritable() && !entity->entity->file) {
|
||||
if (instance->data().isWritable() && !instance->data().file) {
|
||||
// For newly created entities ensure a valid ENTITY_INSTANCE_NAME is set
|
||||
entity->entity->file = this;
|
||||
new_id = entity->entity->isWritable()->setId();
|
||||
instance->data().file = this;
|
||||
new_id = instance->data().isWritable()->setId();
|
||||
} else {
|
||||
new_id = entity->entity->id();
|
||||
new_id = instance->data().id();
|
||||
}
|
||||
|
||||
if (byid.find(new_id) != byid.end()) {
|
||||
// This should not happen
|
||||
std::stringstream ss;
|
||||
ss << "Overwriting entity with id " << new_id;
|
||||
ss << "Overwriting instance with id " << new_id;
|
||||
Logger::Message(Logger::LOG_WARNING, ss.str());
|
||||
}
|
||||
|
||||
// The mapping by entity instance name is updated.
|
||||
byid[new_id] = entity;
|
||||
byid[new_id] = instance;
|
||||
|
||||
// The mapping by reference is updated.
|
||||
IfcEntityList::ptr entity_attributes(new IfcEntityList);
|
||||
try {
|
||||
entity_attributes = traverse(entity, 1);
|
||||
entity_attributes = traverse(instance, 1);
|
||||
} catch (...) {}
|
||||
for (IfcEntityList::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) {
|
||||
IfcUtil::IfcBaseClass* entity_attribute = *it;
|
||||
if (*it == entity) continue;
|
||||
if (*it == instance) continue;
|
||||
try {
|
||||
if (!IfcSchema::Type::IsSimple(entity_attribute->type())) {
|
||||
unsigned entity_attribute_id = entity_attribute->entity->id();
|
||||
// if (!IfcSchema::Type::IsSimple(entity_attribute->type())) {
|
||||
if (!entity_attribute->declaration().as_entity()) {
|
||||
unsigned entity_attribute_id = entity_attribute->data().id();
|
||||
IfcEntityList::ptr refs = entitiesByReference(entity_attribute_id);
|
||||
if (!refs) {
|
||||
refs = IfcEntityList::ptr(new IfcEntityList);
|
||||
byref[entity_attribute_id] = refs;
|
||||
}
|
||||
refs->push(entity);
|
||||
refs->push(instance);
|
||||
}
|
||||
} catch (const IfcParse::IfcException&) {}
|
||||
}
|
||||
|
||||
return entity;
|
||||
return instance;
|
||||
}
|
||||
|
||||
IfcWrite::IfcWritableEntity* make_writable(IfcUtil::IfcBaseClass* instance) {
|
||||
if (instance->entity->isWritable()) {
|
||||
return instance->entity->isWritable();
|
||||
if (instance->data().isWritable()) {
|
||||
return instance->data().isWritable();
|
||||
}
|
||||
|
||||
IfcWrite::IfcWritableEntity* return_value;
|
||||
instance->entity = return_value = new IfcWrite::IfcWritableEntity(instance->entity);
|
||||
IfcWrite::IfcWritableEntity* return_value = new IfcWrite::IfcWritableEntity(&instance->data());
|
||||
instance->data(return_value);
|
||||
return return_value;
|
||||
}
|
||||
|
||||
void IfcFile::removeEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
const unsigned id = entity->entity->id();
|
||||
IfcUtil::IfcBaseClass* file_entity = entityById(id);
|
||||
void IfcFile::removeEntity(IfcUtil::IfcBaseClass* instance) {
|
||||
const unsigned id = instance->data().id();
|
||||
IfcUtil::IfcBaseClass* file_instance = entityById(id);
|
||||
|
||||
// TODO: Create a set of weak relations. Inverse relations that do not dictate an
|
||||
// instance to be retained. For example: when deleting an IfcRepresentation, the
|
||||
@@ -1257,38 +1275,40 @@ void IfcFile::removeEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
// characterized as weak.
|
||||
std::set<IfcSchema::Type::Enum> weak_roots;
|
||||
|
||||
if (entity != file_entity) {
|
||||
if (instance != file_instance) {
|
||||
throw IfcParse::IfcException("Instance not part of this file");
|
||||
}
|
||||
|
||||
std::set<IfcUtil::IfcBaseClass*> deletion_queue;
|
||||
IfcEntityList::ptr references = entitiesByReference(id);
|
||||
|
||||
// Alter entity instances with INVERSE relations to the entity being
|
||||
// Alter entity instances with INVERSE relations to the instance being
|
||||
// deleted. This is necessary to maintain a valid IFC file, because
|
||||
// dangling references to it's entities name should be removed. At this
|
||||
// moment, inversely related instances affected by the removal of the
|
||||
// entity being deleted are not deleted themselves.
|
||||
// instance being deleted are not deleted themselves.
|
||||
if (references) {
|
||||
for (IfcEntityList::it it = references->begin(); it != references->end(); ++it) {
|
||||
IfcUtil::IfcBaseEntity* related_instance = (IfcUtil::IfcBaseEntity*) *it;
|
||||
for (unsigned i = 0; i < related_instance->getArgumentCount(); ++i) {
|
||||
Argument* attr = related_instance->getArgument(i);
|
||||
for (unsigned i = 0; i < related_instance->data().getArgumentCount(); ++i) {
|
||||
|
||||
Argument* attr = related_instance->data().getArgument(i);
|
||||
if (attr->isNull()) continue;
|
||||
|
||||
IfcUtil::ArgumentType attr_type = related_instance->getArgumentType(i);
|
||||
IfcUtil::ArgumentType attr_type = attr->type();
|
||||
|
||||
switch(attr_type) {
|
||||
case IfcUtil::Argument_ENTITY_INSTANCE: {
|
||||
IfcUtil::IfcBaseClass* instance_attribute = *attr;
|
||||
if (instance_attribute == entity) {
|
||||
if (instance_attribute == instance) {
|
||||
make_writable(related_instance)->setArgument(i);
|
||||
// deletion_queue.insert(related_instance);
|
||||
} }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: {
|
||||
IfcEntityList::ptr instance_list = *attr;
|
||||
if (instance_list->contains(entity)) {
|
||||
instance_list->remove(entity);
|
||||
if (instance_list->contains(instance)) {
|
||||
instance_list->remove(instance);
|
||||
make_writable(related_instance)->setArgument(i, instance_list);
|
||||
/* if (instance_list->size() == 0) {
|
||||
deletion_queue.insert(related_instance);
|
||||
@@ -1297,12 +1317,12 @@ void IfcFile::removeEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE: {
|
||||
IfcEntityListList::ptr instance_list_list = *attr;
|
||||
if (instance_list_list->contains(entity)) {
|
||||
if (instance_list_list->contains(instance)) {
|
||||
IfcEntityListList::ptr new_list(new IfcEntityListList);
|
||||
for (IfcEntityListList::outer_it it = instance_list_list->begin(); it != instance_list_list->end(); ++it) {
|
||||
std::vector<IfcUtil::IfcBaseClass*> instances = *it;
|
||||
std::vector<IfcUtil::IfcBaseClass*>::iterator jt;
|
||||
while ((jt = std::find(instances.begin(), instances.end(), entity)) != instances.end()) {
|
||||
while ((jt = std::find(instances.begin(), instances.end(), instance)) != instances.end()) {
|
||||
instances.erase(jt);
|
||||
}
|
||||
new_list->push(instances);
|
||||
@@ -1320,33 +1340,33 @@ void IfcFile::removeEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
byref.erase(byref.find(id));
|
||||
}
|
||||
|
||||
IfcEntityList::ptr entity_attributes = traverse(entity, 1);
|
||||
for (IfcEntityList::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) {
|
||||
IfcUtil::IfcBaseClass* entity_attribute = *it;
|
||||
if (entity_attribute == entity) continue;
|
||||
entitiesByReference(entity_attribute->entity->id())->remove(entity);
|
||||
if (entitiesByReference(entity_attribute->entity->id())->filtered(weak_roots)->size() == 0) {
|
||||
deletion_queue.insert(entity_attribute);
|
||||
IfcEntityList::ptr instance_attributes = traverse(instance, 1);
|
||||
for (IfcEntityList::it it = instance_attributes->begin(); it != instance_attributes->end(); ++it) {
|
||||
IfcUtil::IfcBaseClass* instance_attribute = *it;
|
||||
if (instance_attribute == instance) continue;
|
||||
entitiesByReference(instance_attribute->data().id())->remove(instance);
|
||||
if (entitiesByReference(instance_attribute->data().id())->filtered(weak_roots)->size() == 0) {
|
||||
deletion_queue.insert(instance_attribute);
|
||||
}
|
||||
}
|
||||
|
||||
if (entity->is(IfcSchema::Type::IfcRoot)) {
|
||||
const std::string global_id = ((IfcSchema::IfcRoot*) entity)->GlobalId();
|
||||
IfcSchema::IfcRoot* root = instance->as<IfcSchema::IfcRoot>();
|
||||
if (root) {
|
||||
const std::string global_id = root->GlobalId();
|
||||
byguid.erase(byguid.find(global_id));
|
||||
}
|
||||
|
||||
byid.erase(byid.find(id));
|
||||
|
||||
IfcEntityList::ptr instances_of_same_type = entitiesByType(entity->type());
|
||||
instances_of_same_type->remove(entity);
|
||||
IfcEntityList::ptr instances_of_same_type = entitiesByType(instance->declaration().type());
|
||||
instances_of_same_type->remove(instance);
|
||||
|
||||
while (!deletion_queue.empty()) {
|
||||
removeEntity(*deletion_queue.begin());
|
||||
deletion_queue.erase(deletion_queue.begin());
|
||||
}
|
||||
|
||||
delete entity->entity;
|
||||
delete entity;
|
||||
delete instance;
|
||||
}
|
||||
|
||||
IfcEntityList::ptr IfcFile::entitiesByType(IfcSchema::Type::Enum t) {
|
||||
@@ -1385,7 +1405,6 @@ IfcSchema::IfcRoot* IfcFile::entityByGuid(const std::string& guid) {
|
||||
// FIXME: Test destructor to delete entity and arg allocations
|
||||
IfcFile::~IfcFile() {
|
||||
for( entity_by_id_t::const_iterator it = byid.begin(); it != byid.end(); ++ it ) {
|
||||
delete it->second->entity;
|
||||
delete it->second;
|
||||
}
|
||||
delete stream;
|
||||
@@ -1405,8 +1424,8 @@ std::ostream& operator<< (std::ostream& os, const IfcParse::IfcFile& f) {
|
||||
|
||||
for ( IfcFile::entity_by_id_t::const_iterator it = f.begin(); it != f.end(); ++ it ) {
|
||||
const IfcUtil::IfcBaseClass* e = it->second;
|
||||
if (!IfcSchema::Type::IsSimple(e->type())) {
|
||||
os << e->entity->toString(true) << ";" << std::endl;
|
||||
if (!IfcSchema::Type::IsSimple(e->data().type())) {
|
||||
os << e->data().toString(true) << ";" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1440,9 +1459,9 @@ IfcEntityList::ptr IfcFile::getInverse(int instance_id, IfcSchema::Type::Enum ty
|
||||
if (!all) return l;
|
||||
|
||||
for(IfcEntityList::it it = all->begin(); it != all->end(); ++it) {
|
||||
bool valid = type == IfcSchema::Type::UNDEFINED || (*it)->is(type);
|
||||
bool valid = type == IfcSchema::Type::UNDEFINED || (*it)->declaration().is(type);
|
||||
if (valid && attribute_index >= 0) {
|
||||
Argument* arg = (*it)->entity->getArgument(attribute_index);
|
||||
Argument* arg = (*it)->data().getArgument(attribute_index);
|
||||
if (arg->type() == IfcUtil::Argument_ENTITY_INSTANCE) {
|
||||
valid = instance == *arg;
|
||||
} else if (arg->type() == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
|
||||
@@ -1490,21 +1509,21 @@ std::pair<IfcSchema::IfcNamedUnit*, double> IfcFile::getUnit(IfcSchema::IfcUnitE
|
||||
IfcEntityList::ptr units = project->UnitsInContext()->Units();
|
||||
for (IfcEntityList::it it = units->begin(); it != units->end(); ++it) {
|
||||
IfcSchema::IfcUnit* unit = *it;
|
||||
if (unit->is(IfcSchema::Type::IfcNamedUnit)) {
|
||||
if (unit->declaration().is(IfcSchema::Type::IfcNamedUnit)) {
|
||||
IfcSchema::IfcNamedUnit* named_unit = (IfcSchema::IfcNamedUnit*) unit;
|
||||
if (named_unit->UnitType() != type) {
|
||||
continue;
|
||||
}
|
||||
IfcSchema::IfcSIUnit* unit = 0;
|
||||
if (named_unit->is(IfcSchema::Type::IfcConversionBasedUnit)) {
|
||||
if (named_unit->declaration().is(IfcSchema::Type::IfcConversionBasedUnit)) {
|
||||
IfcSchema::IfcConversionBasedUnit* u = (IfcSchema::IfcConversionBasedUnit*)named_unit;
|
||||
IfcSchema::IfcMeasureWithUnit* mu = u->ConversionFactor();
|
||||
return_value.second *= static_cast<double>(*mu->ValueComponent()->entity->getArgument(0));
|
||||
return_value.second *= static_cast<double>(*mu->ValueComponent()->data().getArgument(0));
|
||||
return_value.first = named_unit;
|
||||
if (mu->UnitComponent()->is(IfcSchema::Type::IfcSIUnit)) {
|
||||
if (mu->UnitComponent()->declaration().is(IfcSchema::Type::IfcSIUnit)) {
|
||||
unit = (IfcSchema::IfcSIUnit*) mu->UnitComponent();
|
||||
}
|
||||
} else if (named_unit->is(IfcSchema::Type::IfcSIUnit)) {
|
||||
} else if (named_unit->declaration().is(IfcSchema::Type::IfcSIUnit)) {
|
||||
return_value.first = unit = (IfcSchema::IfcSIUnit*) named_unit;
|
||||
}
|
||||
if (unit) {
|
||||
|
||||
@@ -257,7 +257,8 @@ namespace IfcParse {
|
||||
std::string datatype() const;
|
||||
IfcSchema::Type::Enum type() const;
|
||||
bool is(IfcSchema::Type::Enum v) const;
|
||||
unsigned int id();
|
||||
unsigned int id() const;
|
||||
const IfcWrite::IfcWritableEntity* isWritable() const;
|
||||
IfcWrite::IfcWritableEntity* isWritable();
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "IfcSchema.h"
|
||||
|
||||
bool IfcParse::declaration::is(const std::string& name) const {
|
||||
return is(IfcSchema::Type::FromString(name));
|
||||
}
|
||||
|
||||
bool IfcParse::declaration::is(IfcSchema::Type::Enum name) const {
|
||||
if (this->as_entity()) {
|
||||
return this->as_entity()->is(name);
|
||||
} else {
|
||||
return this->name() == IfcSchema::Type::ToString(name);
|
||||
}
|
||||
}
|
||||
|
||||
bool IfcParse::named_type::is(const std::string& name) const {
|
||||
return declared_type()->is(name);
|
||||
}
|
||||
|
||||
bool IfcParse::named_type::is(IfcSchema::Type::Enum name) const {
|
||||
return declared_type()->is(name);
|
||||
}
|
||||
+277
-204
@@ -24,222 +24,295 @@
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
class declaration;
|
||||
class type_declaration;
|
||||
class select_type;
|
||||
class enumeration_type;
|
||||
class entity;
|
||||
#ifdef USE_IFC4
|
||||
#include "../ifcparse/Ifc4enum.h"
|
||||
#else
|
||||
#include "../ifcparse/Ifc2x3enum.h"
|
||||
#endif
|
||||
|
||||
class parameter_type {
|
||||
};
|
||||
namespace IfcParse {
|
||||
|
||||
class named_type : public parameter_type {
|
||||
protected:
|
||||
declaration* declared_type_;
|
||||
public:
|
||||
named_type(declaration* declared_type)
|
||||
: declared_type_(declared_type) {}
|
||||
class declaration;
|
||||
|
||||
class type_declaration;
|
||||
class select_type;
|
||||
class enumeration_type;
|
||||
class entity;
|
||||
|
||||
declaration* declared_type() const { return declared_type_; }
|
||||
};
|
||||
class named_type;
|
||||
class simple_type;
|
||||
class aggregation_type;
|
||||
|
||||
class simple_type : public parameter_type {
|
||||
public:
|
||||
typedef enum { binary_type, boolean_type, integer_type, logical_type, number_type, real_type, string_type } data_type;
|
||||
protected:
|
||||
data_type declared_type_;
|
||||
public:
|
||||
simple_type(data_type declared_type)
|
||||
: declared_type_(declared_type) {}
|
||||
class parameter_type {
|
||||
public:
|
||||
virtual const named_type* as_named_type() const { return static_cast<named_type*>(0); }
|
||||
virtual const simple_type* as_simple_type() const { return static_cast<simple_type*>(0); }
|
||||
virtual const aggregation_type* as_aggregation_type() const { return static_cast<aggregation_type*>(0); }
|
||||
|
||||
data_type declared_type() const { return declared_type_; }
|
||||
};
|
||||
virtual bool is(const std::string& name) const { return false; }
|
||||
virtual bool is(IfcSchema::Type::Enum name) const { return false; }
|
||||
};
|
||||
|
||||
class aggregation_type : public parameter_type {
|
||||
public:
|
||||
typedef enum { array_type, bag_type, list_type, set_type } aggregate_type;
|
||||
protected:
|
||||
aggregate_type type_of_aggregation_;
|
||||
int bound1_, bound2_;
|
||||
parameter_type* type_of_element_;
|
||||
public:
|
||||
aggregation_type(aggregate_type type_of_aggregation, int bound1, int bound2, parameter_type* type_of_element)
|
||||
: type_of_aggregation_(type_of_aggregation)
|
||||
, bound1_(bound1)
|
||||
, bound2_(bound2)
|
||||
, type_of_element_(type_of_element)
|
||||
{}
|
||||
|
||||
aggregate_type type_of_aggregation() const { type_of_aggregation_; }
|
||||
int bound1() const { return bound1_; }
|
||||
int bound2() const { return bound2_; }
|
||||
parameter_type* type_of_element() const { return type_of_element_; }
|
||||
};
|
||||
|
||||
class declaration {
|
||||
protected:
|
||||
std::string name_;
|
||||
|
||||
public:
|
||||
declaration(const std::string& name)
|
||||
: name_(name) {}
|
||||
|
||||
const std::string& name() const { return name_; }
|
||||
|
||||
virtual const type_declaration* as_type_declaration() const { return static_cast<type_declaration*>(0); }
|
||||
virtual const select_type* as_select_type() const { return static_cast<select_type*>(0); }
|
||||
virtual const enumeration_type* as_enumeration_type() const { return static_cast<enumeration_type*>(0); }
|
||||
virtual const entity* as_entity() const { return static_cast<entity*>(0); }
|
||||
};
|
||||
|
||||
class type_declaration : public declaration {
|
||||
protected:
|
||||
const parameter_type* declared_type_;
|
||||
|
||||
public:
|
||||
type_declaration(const std::string& name, const parameter_type* declared_type)
|
||||
: declaration(name)
|
||||
, declared_type_(declared_type) {}
|
||||
|
||||
const parameter_type* declared_type() const { return declared_type_; }
|
||||
|
||||
virtual const type_declaration* as_type_declaration() const { return this; }
|
||||
};
|
||||
|
||||
class select_type : public declaration {
|
||||
protected:
|
||||
std::vector<const declaration*> select_list_;
|
||||
public:
|
||||
select_type(const std::string& name, const std::vector<const declaration*>& select_list)
|
||||
: declaration(name)
|
||||
, select_list_(select_list) {}
|
||||
|
||||
const std::vector<const declaration*>& select_list() const { return select_list_; }
|
||||
|
||||
virtual const select_type* as_select_type() const { return this; }
|
||||
};
|
||||
|
||||
class enumeration_type : public declaration {
|
||||
protected:
|
||||
std::vector<std::string> enumeration_items_;
|
||||
public:
|
||||
enumeration_type(const std::string& name, const std::vector<std::string>& enumeration_items)
|
||||
: declaration(name)
|
||||
, enumeration_items_(enumeration_items) {}
|
||||
|
||||
const std::vector<std::string>& enumeration_items() const { return enumeration_items_; }
|
||||
|
||||
virtual const enumeration_type* as_enumeration_type() const { return this; }
|
||||
};
|
||||
|
||||
class entity : public declaration {
|
||||
public:
|
||||
class attribute {
|
||||
class named_type : public parameter_type {
|
||||
protected:
|
||||
declaration* declared_type_;
|
||||
public:
|
||||
named_type(declaration* declared_type)
|
||||
: declared_type_(declared_type) {}
|
||||
|
||||
declaration* declared_type() const { return declared_type_; }
|
||||
|
||||
virtual const named_type* as_named_type() const { return this; }
|
||||
|
||||
virtual bool is(const std::string& name) const;
|
||||
virtual bool is(IfcSchema::Type::Enum name) const;
|
||||
};
|
||||
|
||||
class simple_type : public parameter_type {
|
||||
public:
|
||||
typedef enum { binary_type, boolean_type, integer_type, logical_type, number_type, real_type, string_type } data_type;
|
||||
protected:
|
||||
data_type declared_type_;
|
||||
public:
|
||||
simple_type(data_type declared_type)
|
||||
: declared_type_(declared_type) {}
|
||||
|
||||
data_type declared_type() const { return declared_type_; }
|
||||
|
||||
virtual const simple_type* as_simple_type() const { return this; }
|
||||
};
|
||||
|
||||
class aggregation_type : public parameter_type {
|
||||
public:
|
||||
typedef enum { array_type, bag_type, list_type, set_type } aggregate_type;
|
||||
protected:
|
||||
aggregate_type type_of_aggregation_;
|
||||
int bound1_, bound2_;
|
||||
parameter_type* type_of_element_;
|
||||
public:
|
||||
aggregation_type(aggregate_type type_of_aggregation, int bound1, int bound2, parameter_type* type_of_element)
|
||||
: type_of_aggregation_(type_of_aggregation)
|
||||
, bound1_(bound1)
|
||||
, bound2_(bound2)
|
||||
, type_of_element_(type_of_element)
|
||||
{}
|
||||
|
||||
aggregate_type type_of_aggregation() const { type_of_aggregation_; }
|
||||
int bound1() const { return bound1_; }
|
||||
int bound2() const { return bound2_; }
|
||||
parameter_type* type_of_element() const { return type_of_element_; }
|
||||
|
||||
virtual const aggregation_type* as_aggregation_type() const { return this; }
|
||||
};
|
||||
|
||||
class declaration {
|
||||
protected:
|
||||
// std::string name_;
|
||||
IfcSchema::Type::Enum name_;
|
||||
|
||||
public:
|
||||
declaration(IfcSchema::Type::Enum name)
|
||||
: name_(name) {}
|
||||
declaration(const std::string& name)
|
||||
: name_(IfcSchema::Type::FromString(name)) {}
|
||||
|
||||
std::string name() const { return IfcSchema::Type::ToString(name_); }
|
||||
|
||||
virtual const type_declaration* as_type_declaration() const { return static_cast<type_declaration*>(0); }
|
||||
virtual const select_type* as_select_type() const { return static_cast<select_type*>(0); }
|
||||
virtual const enumeration_type* as_enumeration_type() const { return static_cast<enumeration_type*>(0); }
|
||||
virtual const entity* as_entity() const { return static_cast<entity*>(0); }
|
||||
|
||||
// TODO: Type checking by Enum value
|
||||
bool is(const std::string& name) const;
|
||||
bool is(IfcSchema::Type::Enum name) const;
|
||||
|
||||
IfcSchema::Type::Enum type() const {
|
||||
return name_;
|
||||
}
|
||||
};
|
||||
|
||||
class type_declaration : public declaration {
|
||||
protected:
|
||||
const parameter_type* declared_type_;
|
||||
|
||||
public:
|
||||
type_declaration(const std::string& name, const parameter_type* declared_type)
|
||||
: declaration(name)
|
||||
, declared_type_(declared_type) {}
|
||||
type_declaration(IfcSchema::Type::Enum name, const parameter_type* declared_type)
|
||||
: declaration(name)
|
||||
, declared_type_(declared_type) {}
|
||||
|
||||
const parameter_type* declared_type() const { return declared_type_; }
|
||||
|
||||
virtual const type_declaration* as_type_declaration() const { return this; }
|
||||
};
|
||||
|
||||
class select_type : public declaration {
|
||||
protected:
|
||||
std::vector<const declaration*> select_list_;
|
||||
public:
|
||||
select_type(const std::string& name, const std::vector<const declaration*>& select_list)
|
||||
: declaration(name)
|
||||
, select_list_(select_list) {}
|
||||
select_type(IfcSchema::Type::Enum name, const std::vector<const declaration*>& select_list)
|
||||
: declaration(name)
|
||||
, select_list_(select_list) {}
|
||||
|
||||
const std::vector<const declaration*>& select_list() const { return select_list_; }
|
||||
|
||||
virtual const select_type* as_select_type() const { return this; }
|
||||
};
|
||||
|
||||
class enumeration_type : public declaration {
|
||||
protected:
|
||||
std::vector<std::string> enumeration_items_;
|
||||
public:
|
||||
enumeration_type(const std::string& name, const std::vector<std::string>& enumeration_items)
|
||||
: declaration(name)
|
||||
, enumeration_items_(enumeration_items) {}
|
||||
enumeration_type(IfcSchema::Type::Enum name, const std::vector<std::string>& enumeration_items)
|
||||
: declaration(name)
|
||||
, enumeration_items_(enumeration_items) {}
|
||||
|
||||
const std::vector<std::string>& enumeration_items() const { return enumeration_items_; }
|
||||
|
||||
virtual const enumeration_type* as_enumeration_type() const { return this; }
|
||||
};
|
||||
|
||||
class entity : public declaration {
|
||||
public:
|
||||
class attribute {
|
||||
protected:
|
||||
std::string name_;
|
||||
const parameter_type* type_of_attribute_;
|
||||
bool optional_;
|
||||
|
||||
public:
|
||||
attribute(const std::string& name, parameter_type* type_of_attribute, bool optional)
|
||||
: name_(name)
|
||||
, type_of_attribute_(type_of_attribute)
|
||||
, optional_(optional) {}
|
||||
|
||||
const std::string& name() const { return name_; }
|
||||
const parameter_type* type_of_attribute() const { return type_of_attribute_; }
|
||||
bool optional() const { return optional_; }
|
||||
};
|
||||
|
||||
protected:
|
||||
const entity* supertype_; /* NB: IFC explicitly allows only single inheritance */
|
||||
std::vector<const entity*> subtypes_;
|
||||
|
||||
std::vector<const attribute*> attributes_;
|
||||
std::vector<bool> derived_;
|
||||
|
||||
public:
|
||||
entity(const std::string& name, entity* supertype)
|
||||
: declaration(name)
|
||||
, supertype_(supertype)
|
||||
{}
|
||||
entity(IfcSchema::Type::Enum name, entity* supertype)
|
||||
: declaration(name)
|
||||
, supertype_(supertype)
|
||||
{}
|
||||
|
||||
bool is(const std::string& name) const {
|
||||
return is(IfcSchema::Type::FromString(name));
|
||||
}
|
||||
|
||||
bool is(IfcSchema::Type::Enum name) const {
|
||||
if (name == name_) return true;
|
||||
else if (supertype_) return supertype_->is(name);
|
||||
else return false;
|
||||
}
|
||||
|
||||
void set_subtypes(const std::vector<const entity*>& subtypes) {
|
||||
subtypes_ = subtypes;
|
||||
}
|
||||
|
||||
void set_attributes(const std::vector<const attribute*>& attributes, const std::vector<bool>& derived) {
|
||||
attributes_ = attributes;
|
||||
derived_ = derived;
|
||||
}
|
||||
|
||||
const std::vector<const entity*>& subtypes() const { return subtypes_; }
|
||||
const std::vector<const attribute*>& attributes() const { return attributes_; }
|
||||
const std::vector<bool>& derived() const { return derived_; }
|
||||
|
||||
const std::vector<const attribute*> all_attributes() const {
|
||||
std::vector<const attribute*> attrs;
|
||||
attrs.reserve(derived_.size());
|
||||
std::vector<const attribute*>::iterator it = attrs.begin();
|
||||
if (supertype_) {
|
||||
const std::vector<const attribute*> supertype_attrs = supertype_->all_attributes();
|
||||
it = std::copy(supertype_attrs.begin(), supertype_attrs.end(), it);
|
||||
}
|
||||
std::copy(attributes_.begin(), attributes_.end(), it);
|
||||
return attrs;
|
||||
}
|
||||
|
||||
virtual const entity* as_entity() const { return this; }
|
||||
};
|
||||
|
||||
class schema_definition {
|
||||
private:
|
||||
bool built_in_;
|
||||
|
||||
std::string name_;
|
||||
const parameter_type* type_of_attribute_;
|
||||
bool optional_;
|
||||
|
||||
std::vector<const declaration*> declarations_;
|
||||
|
||||
std::vector<const type_declaration*> type_declarations_;
|
||||
std::vector<const select_type*> select_types_;
|
||||
std::vector<const enumeration_type*> enumeration_types_;
|
||||
|
||||
class declaration_by_name_cmp : public std::binary_function<const declaration*, const std::string&, bool> {
|
||||
public:
|
||||
bool operator()(const declaration* decl, const std::string& name) {
|
||||
return decl->name() < name;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
attribute(const std::string& name, parameter_type* type_of_attribute, bool optional)
|
||||
schema_definition(const std::string& name, const std::vector<const declaration*>& declarations, const bool built_in = false)
|
||||
: name_(name)
|
||||
, type_of_attribute_(type_of_attribute)
|
||||
, optional_(optional) {}
|
||||
, declarations_(declarations)
|
||||
, built_in_(built_in)
|
||||
{
|
||||
for (std::vector<const declaration*>::const_iterator it = declarations_.begin(); it != declarations_.end(); ++it) {
|
||||
if ((**it).as_type_declaration()) type_declarations_.push_back((**it).as_type_declaration());
|
||||
if ((**it).as_select_type()) select_types_.push_back((**it).as_select_type());
|
||||
if ((**it).as_enumeration_type()) enumeration_types_.push_back((**it).as_enumeration_type());
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& name() const { return name_; }
|
||||
const parameter_type* type_of_attribute() const { return type_of_attribute_; }
|
||||
bool optional() const { return optional_; }
|
||||
~schema_definition() {
|
||||
for (std::vector<const declaration*>::const_iterator it = declarations_.begin(); it != declarations_.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
const declaration* declaration_by_name(const std::string& name) const {
|
||||
std::vector<const declaration*>::const_iterator it = std::lower_bound(declarations_.begin(), declarations_.end(), name, declaration_by_name_cmp());
|
||||
if (it == declarations_.end() || (**it).name() != name) {
|
||||
throw;
|
||||
} else {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
|
||||
const declaration* declaration_by_name(IfcSchema::Type::Enum name) const {
|
||||
if (!built_in_) throw;
|
||||
return declaration_by_name(IfcSchema::Type::ToString(name));
|
||||
}
|
||||
|
||||
const std::vector<const declaration*>& declarations() { return declarations_; }
|
||||
const std::vector<const type_declaration*>& type_declarations() { return type_declarations_; }
|
||||
const std::vector<const select_type*>& select_types() { return select_types_; }
|
||||
const std::vector<const enumeration_type*>& enumeration_types() { return enumeration_types_; }
|
||||
};
|
||||
|
||||
protected:
|
||||
const entity* supertype_; /* NB: IFC explicitly allows only single inheritance */
|
||||
std::vector<const entity*> subtypes_;
|
||||
}
|
||||
|
||||
std::vector<const attribute*> attributes_;
|
||||
std::vector<bool> derived_;
|
||||
|
||||
public:
|
||||
entity(const std::string& name, entity* supertype)
|
||||
: declaration(name)
|
||||
, supertype_(supertype)
|
||||
{}
|
||||
|
||||
void set_subtypes(const std::vector<const entity*>& subtypes) {
|
||||
subtypes_ = subtypes;
|
||||
}
|
||||
|
||||
void set_attributes(const std::vector<const attribute*>& attributes, const std::vector<bool>& derived) {
|
||||
attributes_ = attributes;
|
||||
derived_ = derived;
|
||||
}
|
||||
|
||||
const std::vector<const entity*>& subtypes() const { return subtypes_; }
|
||||
const std::vector<const attribute*>& attributes() const { return attributes_; }
|
||||
const std::vector<bool>& derived() const { return derived_; }
|
||||
|
||||
const std::vector<const attribute*> all_attributes() const {
|
||||
std::vector<const attribute*> attrs;
|
||||
attrs.reserve(derived_.size());
|
||||
std::vector<const attribute*>::iterator it = attrs.begin();
|
||||
if (supertype_) {
|
||||
const std::vector<const attribute*> supertype_attrs = supertype_->all_attributes();
|
||||
it = std::copy(supertype_attrs.begin(), supertype_attrs.end(), it);
|
||||
}
|
||||
std::copy(attributes_.begin(), attributes_.end(), it);
|
||||
return attrs;
|
||||
}
|
||||
|
||||
virtual const entity* as_entity() const { return this; }
|
||||
};
|
||||
|
||||
class schema_definition {
|
||||
private:
|
||||
std::string name_;
|
||||
|
||||
std::vector<const declaration*> declarations_;
|
||||
|
||||
std::vector<const type_declaration*> type_declarations_;
|
||||
std::vector<const select_type*> select_types_;
|
||||
std::vector<const enumeration_type*> enumeration_types_;
|
||||
|
||||
class declaration_by_name_cmp : public std::binary_function<const declaration*, const std::string&, bool> {
|
||||
public:
|
||||
bool operator()(const declaration* decl, const std::string& name) {
|
||||
return decl->name() < name;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
schema_definition(const std::string& name, const std::vector<const declaration*>& declarations)
|
||||
: name_(name)
|
||||
, declarations_(declarations)
|
||||
{
|
||||
for (std::vector<const declaration*>::const_iterator it = declarations_.begin(); it != declarations_.end(); ++it) {
|
||||
if ((**it).as_type_declaration()) type_declarations_.push_back((**it).as_type_declaration());
|
||||
if ((**it).as_select_type()) select_types_.push_back((**it).as_select_type());
|
||||
if ((**it).as_enumeration_type()) enumeration_types_.push_back((**it).as_enumeration_type());
|
||||
}
|
||||
}
|
||||
|
||||
~schema_definition() {
|
||||
for (std::vector<const declaration*>::const_iterator it = declarations_.begin(); it != declarations_.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
const declaration* declaration_by_name(const std::string& name) {
|
||||
std::vector<const declaration*>::const_iterator it = std::lower_bound(declarations_.begin(), declarations_.end(), name, declaration_by_name_cmp());
|
||||
if (it == declarations_.end() || (**it).name() != name) {
|
||||
throw;
|
||||
} else {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<const declaration*>& declarations() { return declarations_; }
|
||||
const std::vector<const type_declaration*>& type_declarations() { return type_declarations_; }
|
||||
const std::vector<const select_type*>& select_types() { return select_types_; }
|
||||
const std::vector<const enumeration_type*>& enumeration_types() { return enumeration_types_; }
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -91,7 +91,11 @@ public:
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
unsigned int id() {
|
||||
unsigned int id() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const IfcWrite::IfcWritableEntity* isWritable() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ IfcEntityList::ptr IfcEntityList::filtered(const std::set<IfcSchema::Type::Enum>
|
||||
for (it it = begin(); it != end(); ++it) {
|
||||
bool contained = false;
|
||||
for (std::set<IfcSchema::Type::Enum>::const_iterator jt = entities.begin(); jt != entities.end(); ++jt) {
|
||||
if ((*it)->is(*jt)) {
|
||||
if ((*it)->declaration().is(*jt)) {
|
||||
contained = true;
|
||||
break;
|
||||
}
|
||||
@@ -69,9 +69,9 @@ IfcEntityList::ptr IfcEntityList::filtered(const std::set<IfcSchema::Type::Enum>
|
||||
}
|
||||
|
||||
|
||||
unsigned int IfcUtil::IfcBaseType::getArgumentCount() const { return 1; }
|
||||
Argument* IfcUtil::IfcBaseType::getArgument(unsigned int i) const { return entity->getArgument(i); }
|
||||
const char* IfcUtil::IfcBaseType::getArgumentName(unsigned int i) const { if (i == 0) { return "wrappedValue"; } else { throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); } }
|
||||
// unsigned int IfcUtil::IfcBaseType::getArgumentCount() const { return 1; }
|
||||
// Argument* IfcUtil::IfcBaseType::getArgument(unsigned int i) const { return entity->getArgument(i); }
|
||||
// const char* IfcUtil::IfcBaseType::getArgumentName(unsigned int i) const { if (i == 0) { return "wrappedValue"; } else { throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); } }
|
||||
|
||||
void Logger::SetOutput(std::ostream* l1, std::ostream* l2) {
|
||||
log1 = l1;
|
||||
@@ -80,10 +80,10 @@ void Logger::SetOutput(std::ostream* l1, std::ostream* l2) {
|
||||
log2 = &log_stream;
|
||||
}
|
||||
}
|
||||
void Logger::Message(Logger::Severity type, const std::string& message, IfcAbstractEntity* entity) {
|
||||
void Logger::Message(Logger::Severity type, const std::string& message, const IfcUtil::IfcBaseClass* entity) {
|
||||
if ( log2 && type >= verbosity ) {
|
||||
(*log2) << "[" << severity_strings[type] << "] " << message << std::endl;
|
||||
if ( entity ) (*log2) << entity->toString() << std::endl;
|
||||
if ( entity ) (*log2) << entity->data().toString() << std::endl;
|
||||
}
|
||||
}
|
||||
void Logger::Status(const std::string& message, bool new_line) {
|
||||
@@ -143,4 +143,13 @@ bool IfcUtil::valid_binary_string(const std::string& s) {
|
||||
if (*it != '0' && *it != '1') return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
IfcUtil::IfcBaseClass::~IfcBaseClass() {
|
||||
delete data_;
|
||||
}
|
||||
|
||||
void IfcUtil::IfcBaseClass::data(IfcAbstractEntity* d) {
|
||||
delete data_;
|
||||
data_ = d;
|
||||
}
|
||||
+45
-18
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <boost/dynamic_bitset.hpp>
|
||||
|
||||
#include "../ifcparse/IfcSchema.h"
|
||||
#include "../ifcparse/SharedPointer.h"
|
||||
|
||||
#ifdef USE_IFC4
|
||||
@@ -40,6 +41,13 @@ class Argument;
|
||||
class IfcEntityList;
|
||||
class IfcEntityListList;
|
||||
class IfcAbstractEntity;
|
||||
|
||||
namespace IfcParse { // these have to be declared first in order for the virtual function below to be covariant. separate into different header file
|
||||
class declaration;
|
||||
class entity;
|
||||
class type_declaration;
|
||||
}
|
||||
|
||||
namespace IfcWrite {
|
||||
class IfcWritableEntity;
|
||||
}
|
||||
@@ -72,35 +80,53 @@ namespace IfcUtil {
|
||||
const char* ArgumentTypeToString(ArgumentType argument_type);
|
||||
|
||||
class IfcBaseClass {
|
||||
protected:
|
||||
IfcAbstractEntity* data_;
|
||||
public:
|
||||
IfcAbstractEntity* entity;
|
||||
virtual bool is(IfcSchema::Type::Enum v) const = 0;
|
||||
virtual IfcSchema::Type::Enum type() const = 0;
|
||||
IfcBaseClass() : data_(0) {}
|
||||
IfcBaseClass(IfcAbstractEntity* d) : data_(d) {}
|
||||
virtual ~IfcBaseClass();
|
||||
|
||||
virtual unsigned int getArgumentCount() const = 0;
|
||||
virtual ArgumentType getArgumentType(unsigned int i) const = 0;
|
||||
virtual IfcSchema::Type::Enum getArgumentEntity(unsigned int i) const = 0;
|
||||
virtual Argument* getArgument(unsigned int i) const = 0;
|
||||
virtual const char* getArgumentName(unsigned int i) const = 0;
|
||||
const IfcAbstractEntity& data() const { return *data_; }
|
||||
IfcAbstractEntity& data() { return *data_; }
|
||||
|
||||
void data(IfcAbstractEntity* d);
|
||||
|
||||
virtual const IfcParse::declaration& declaration() const = 0;
|
||||
|
||||
template <class T>
|
||||
T* as() {
|
||||
return is(T::Class())
|
||||
return declaration().is(T::Class())
|
||||
? static_cast<T*>(this)
|
||||
: static_cast<T*>(0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const T* as() const {
|
||||
return declaration().is(T::Class())
|
||||
? static_cast<const T*>(this)
|
||||
: static_cast<const T*>(0);
|
||||
}
|
||||
private:
|
||||
IfcBaseClass(const IfcBaseClass&);
|
||||
IfcBaseClass& operator=(const IfcBaseClass&);
|
||||
};
|
||||
|
||||
class IfcBaseEntity : public IfcBaseClass {
|
||||
public:
|
||||
IfcBaseEntity() : IfcBaseClass() {}
|
||||
IfcBaseEntity(IfcAbstractEntity* d) : IfcBaseClass(d) {}
|
||||
|
||||
virtual const IfcParse::entity& declaration() const = 0;
|
||||
};
|
||||
|
||||
// TODO: Investigate whether these should be template classes instead
|
||||
class IfcBaseType : public IfcBaseEntity {
|
||||
class IfcBaseType : public IfcBaseClass {
|
||||
public:
|
||||
unsigned int getArgumentCount() const;
|
||||
Argument* getArgument(unsigned int i) const;
|
||||
const char* getArgumentName(unsigned int i) const;
|
||||
IfcSchema::Type::Enum getArgumentEntity(unsigned int i) const { return IfcSchema::Type::UNDEFINED; }
|
||||
IfcBaseType() : IfcBaseClass() {}
|
||||
IfcBaseType(IfcAbstractEntity* d) : IfcBaseClass(d) {}
|
||||
|
||||
virtual const IfcParse::type_declaration& declaration() const = 0;
|
||||
};
|
||||
|
||||
bool valid_binary_string(const std::string& s);
|
||||
@@ -125,7 +151,7 @@ public:
|
||||
typename U::list::ptr as() {
|
||||
typename U::list::ptr r(new typename U::list);
|
||||
const bool all = U::Class() == IfcSchema::Type::UNDEFINED;
|
||||
for ( it i = begin(); i != end(); ++ i ) if (all || (*i)->is(U::Class())) r->push((U*)*i);
|
||||
for ( it i = begin(); i != end(); ++ i ) if (all || (*i)->declaration().is(U::Class())) r->push((U*)*i);
|
||||
return r;
|
||||
}
|
||||
void remove(IfcUtil::IfcBaseClass*);
|
||||
@@ -153,7 +179,7 @@ public:
|
||||
typename U::list::ptr as() {
|
||||
typename U::list::ptr r(new typename U::list);
|
||||
const bool all = U::Class() == IfcSchema::Type::UNDEFINED;
|
||||
for ( it i = begin(); i != end(); ++ i ) if (all || (*i)->is(U::Class())) r->push((U*)*i);
|
||||
for ( it i = begin(); i != end(); ++ i ) if (all || (*i)->declaration().is(U::Class())) r->push((U*)*i);
|
||||
return r;
|
||||
}
|
||||
void remove(T* t) {
|
||||
@@ -305,7 +331,8 @@ public:
|
||||
virtual IfcSchema::Type::Enum type() const = 0;
|
||||
virtual bool is(IfcSchema::Type::Enum v) const = 0;
|
||||
virtual std::string toString(bool upper=false) const = 0;
|
||||
virtual unsigned int id() = 0;
|
||||
virtual unsigned int id() const = 0;
|
||||
virtual const IfcWrite::IfcWritableEntity* isWritable() const = 0;
|
||||
virtual IfcWrite::IfcWritableEntity* isWritable() = 0;
|
||||
};
|
||||
|
||||
@@ -325,7 +352,7 @@ public:
|
||||
static void Verbosity(Severity v);
|
||||
static Severity Verbosity();
|
||||
/// Log a message to the output stream
|
||||
static void Message(Severity type, const std::string& message, IfcAbstractEntity* entity=0);
|
||||
static void Message(Severity type, const std::string& message, const IfcUtil::IfcBaseClass* instance=0);
|
||||
static void Status(const std::string& message, bool new_line=true);
|
||||
static void ProgressBar(int progress);
|
||||
static std::string GetLog();
|
||||
|
||||
@@ -40,12 +40,17 @@
|
||||
namespace IfcWrite {
|
||||
class IfcWritableEntity : public IfcAbstractEntity {
|
||||
private:
|
||||
// Mutable because calling id() will generate a fresh id on
|
||||
// the current file, in case none has been assigned previously
|
||||
mutable int* _id;
|
||||
|
||||
std::map<int,bool> writemask;
|
||||
std::map<int,Argument*> args;
|
||||
IfcSchema::Type::Enum _type;
|
||||
int* _id;
|
||||
|
||||
bool arg_writable(int i);
|
||||
void arg_writable(int i, bool b);
|
||||
|
||||
template <typename T> void _setArgument(int i, const T&);
|
||||
public:
|
||||
IfcWritableEntity(IfcSchema::Type::Enum t);
|
||||
@@ -60,7 +65,8 @@ namespace IfcWrite {
|
||||
IfcSchema::Type::Enum type() const;
|
||||
bool is(IfcSchema::Type::Enum v) const;
|
||||
std::string toString(bool upper=false) const;
|
||||
unsigned int id();
|
||||
unsigned int id() const;
|
||||
const IfcWritableEntity* isWritable() const;
|
||||
IfcWritableEntity* isWritable();
|
||||
|
||||
void setArgument(int i, Argument* a);
|
||||
|
||||
@@ -109,12 +109,13 @@ std::string IfcWritableEntity::toString(bool upper) const {
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
unsigned int IfcWritableEntity::id() {
|
||||
unsigned int IfcWritableEntity::id() const {
|
||||
if ( !_id ) {
|
||||
_id = new int(file->FreshId());
|
||||
}
|
||||
return *_id;
|
||||
}
|
||||
const IfcWritableEntity* IfcWritableEntity::isWritable() const { return this; }
|
||||
IfcWritableEntity* IfcWritableEntity::isWritable() { return this; }
|
||||
bool IfcWritableEntity::arg_writable(int i) {
|
||||
std::map<int,bool>::const_iterator it = writemask.find(i);
|
||||
@@ -390,11 +391,11 @@ public:
|
||||
data << "." << i.enumeration_value << ".";
|
||||
}
|
||||
void operator()(const IfcUtil::IfcBaseClass* const& i) {
|
||||
IfcAbstractEntity* e = i->entity;
|
||||
if ( IfcSchema::Type::IsSimple(e->type()) ) {
|
||||
data << e->toString(upper);
|
||||
const IfcAbstractEntity& e = i->data();
|
||||
if ( IfcSchema::Type::IsSimple(e.type()) ) {
|
||||
data << e.toString(upper);
|
||||
} else {
|
||||
data << "#" << e->id();
|
||||
data << "#" << e.id();
|
||||
}
|
||||
}
|
||||
void operator()(const IfcEntityList::ptr& i) {
|
||||
|
||||
Reference in New Issue
Block a user