mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-17 02:49:12 +00:00
1) Implement a breadth-first traversal of forward references 2) implement entity instance deletion from a file 3) recursively copy entity instances to another file
This commit is contained in:
@@ -103,6 +103,11 @@ class Header:
|
||||
argument_type_function_body_tail = (" return %s::getArgumentType(i); "%type.supertypes[0]) if len(type.supertypes) == 1 else ' throw IfcParse::IfcException("argument out of range"); '
|
||||
|
||||
argument_type_function_body = argument_type_function_body_switch_stmt + argument_type_function_body_tail
|
||||
|
||||
argument_entity_function_body_switch_stmt = " switch (i) {%s}"%("".join(['case %d: return %s; '%(i+argument_start, mapping.make_argument_entity(attr)) for i, attr in enumerate(type.attributes)])) if len(type.attributes) else ""
|
||||
argument_entity_function_body_tail = (" return %s::getArgumentEntity(i); "%type.supertypes[0]) if len(type.supertypes) == 1 else ' throw IfcParse::IfcException("argument out of range"); '
|
||||
|
||||
argument_entity_function_body = argument_entity_function_body_switch_stmt + argument_entity_function_body_tail
|
||||
|
||||
constructor_arguments = ", ".join("%(full_type)s v%(index)d_%(name)s"%a for a in mapping.get_assignable_arguments(type))
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ class LateBoundImplementation:
|
||||
entity_descriptors.append(templates.entity_descriptor % {
|
||||
'type' : name,
|
||||
'parent_statement' : '0',
|
||||
'entity_descriptor_attributes' : templates.entity_descriptor_attribute % {
|
||||
'entity_descriptor_attributes' : templates.entity_descriptor_attribute_without_entity % {
|
||||
'name' : 'wrappedValue',
|
||||
'optional' : 'false',
|
||||
'type' : mapping.make_argument_type(mapping.schema.types[name].type)
|
||||
@@ -49,12 +49,14 @@ class LateBoundImplementation:
|
||||
entity_descriptor_attributes = []
|
||||
for arg in constructor_arguments:
|
||||
if not arg['is_inherited']:
|
||||
tmpl = templates.entity_descriptor_attribute_enum if arg['argument_type_enum'] == 'IfcUtil::Argument_ENUMERATION' else templates.entity_descriptor_attribute
|
||||
is_enumeration = arg['argument_type_enum'] == 'IfcUtil::Argument_ENUMERATION'
|
||||
tmpl = templates.entity_descriptor_attribute_with_entity
|
||||
entity_name = arg['argument_type'] if is_enumeration else arg['argument_entity'].split('::')[1]
|
||||
entity_descriptor_attributes.append(tmpl % {
|
||||
'name' : arg['name'],
|
||||
'optional' : 'true' if arg['is_optional'] else 'false',
|
||||
'type' : arg['argument_type_enum'],
|
||||
'enum_type' : arg['argument_type']
|
||||
'name' : arg['name'],
|
||||
'optional' : 'true' if arg['is_optional'] else 'false',
|
||||
'type' : arg['argument_type_enum'],
|
||||
'entity_name': entity_name
|
||||
})
|
||||
|
||||
emitted_entities.add(name)
|
||||
|
||||
@@ -66,6 +66,12 @@ class Mapping:
|
||||
return self.is_array(self.schema.types[type].type.type)
|
||||
else:
|
||||
return False
|
||||
|
||||
def make_argument_entity(self, attr):
|
||||
type = attr.type if hasattr(attr, 'type') else attr
|
||||
while isinstance(type, nodes.AggregationType): type = type.type
|
||||
if type in self.express_to_cpp_typemapping or isinstance(type, nodes.BinaryType): return "Type::UNDEFINED"
|
||||
else: return "Type::%s" % type
|
||||
|
||||
def make_argument_type(self, attr):
|
||||
def _make_argument_type(type):
|
||||
@@ -191,6 +197,7 @@ class Mapping:
|
||||
'is_derived' : attr.name in derived,
|
||||
'is_templated_list' : self.is_templated_list(attr),
|
||||
'argument_type_enum' : self.make_argument_type(attr),
|
||||
'argument_entity' : self.make_argument_entity(attr),
|
||||
'argument_type' : attr.type
|
||||
} for i, attr in attrs if include(attr)]
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace %(schema_name)s {
|
||||
|
||||
namespace Type {
|
||||
typedef enum {
|
||||
%(types)s, ALL
|
||||
%(types)s, UNDEFINED
|
||||
} Enum;
|
||||
Enum Parent(Enum v);
|
||||
Enum FromString(const std::string& s);
|
||||
@@ -88,12 +88,12 @@ namespace Type {
|
||||
int GetAttributeCount(Enum t);
|
||||
int GetAttributeIndex(Enum t, const std::string& a);
|
||||
IfcUtil::ArgumentType GetAttributeType(Enum t, unsigned char a);
|
||||
Enum GetAttributeEntity(Enum t, unsigned char a);
|
||||
const std::string& GetAttributeName(Enum t, unsigned char a);
|
||||
bool GetAttributeOptional(Enum t, unsigned char a);
|
||||
bool GetAttributeDerived(Enum t, unsigned char a);
|
||||
std::pair<const char*, int> GetEnumerationIndex(Enum t, const std::string& a);
|
||||
std::pair<Enum, unsigned> GetInverseAttribute(Enum t, const std::string& a);
|
||||
Enum GetAttributeEnumerationClass(Enum t, unsigned char a);
|
||||
void PopulateDerivedFields(IfcWrite::IfcWritableEntity* e);
|
||||
}}
|
||||
|
||||
@@ -211,6 +211,13 @@ ArgumentType Type::GetAttributeType(Enum t, unsigned char a) {
|
||||
else return i->second->getArgumentType(a);
|
||||
}
|
||||
|
||||
Type::Enum Type::GetAttributeEntity(Enum t, unsigned char a) {
|
||||
if (entity_descriptor_map.empty()) ::InitDescriptorMap();
|
||||
std::map<Type::Enum,IfcEntityDescriptor*>::const_iterator i = entity_descriptor_map.find(t);
|
||||
if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found");
|
||||
else return i->second->getArgumentEntity(a);
|
||||
}
|
||||
|
||||
const std::string& Type::GetAttributeName(Enum t, unsigned char a) {
|
||||
if (entity_descriptor_map.empty()) ::InitDescriptorMap();
|
||||
std::map<Type::Enum,IfcEntityDescriptor*>::const_iterator i = entity_descriptor_map.find(t);
|
||||
@@ -250,17 +257,6 @@ std::pair<Type::Enum, unsigned> Type::GetInverseAttribute(Enum t, const std::str
|
||||
throw IfcException("Attribute not found");
|
||||
}
|
||||
|
||||
Type::Enum Type::GetAttributeEnumerationClass(Enum t, unsigned char a) {
|
||||
if (entity_descriptor_map.empty()) ::InitDescriptorMap();
|
||||
std::map<Type::Enum,IfcEntityDescriptor*>::const_iterator i = entity_descriptor_map.find(t);
|
||||
if ( i == entity_descriptor_map.end() ) throw IfcException("Type not found");
|
||||
else {
|
||||
Type::Enum t = i->second->getArgumentEnumerationClass(a);
|
||||
if ( t == Type::ALL ) throw IfcException("Not an enumeration");
|
||||
else return t;
|
||||
}
|
||||
}
|
||||
|
||||
void Type::PopulateDerivedFields(IfcWrite::IfcWritableEntity* e) {
|
||||
std::map<Type::Enum, std::set<int> >::const_iterator i = derived_map.find(e->type());
|
||||
if (i != derived_map.end()) {
|
||||
@@ -275,8 +271,8 @@ entity_descriptor = """ current = entity_descriptor_map[Type::%(type)s] = new
|
||||
%(entity_descriptor_attributes)s"""
|
||||
|
||||
entity_descriptor_parent = "entity_descriptor_map.find(Type::%(type)s)->second"
|
||||
entity_descriptor_attribute = ' current->add("%(name)s",%(optional)s,%(type)s);'
|
||||
entity_descriptor_attribute_enum = ' current->add("%(name)s",%(optional)s,%(type)s,Type::%(enum_type)s);'
|
||||
entity_descriptor_attribute_without_entity = ' current->add("%(name)s",%(optional)s,%(type)s);'
|
||||
entity_descriptor_attribute_with_entity = ' current->add("%(name)s",%(optional)s,%(type)s,Type::%(entity_name)s);'
|
||||
|
||||
enumeration_descriptor = """ values.clear(); values.reserve(128);
|
||||
%(enumeration_descriptor_values)s
|
||||
@@ -329,6 +325,7 @@ class %(name)s %(superclass)s{
|
||||
public:
|
||||
%(attributes)s virtual unsigned int getArgumentCount() const { return %(argument_count)d; }
|
||||
virtual IfcUtil::ArgumentType getArgumentType(unsigned int i) const {%(argument_type_function_body)s}
|
||||
virtual Type::Enum getArgumentEntity(unsigned int i) const {%(argument_entity_function_body)s}
|
||||
virtual const char* getArgumentName(unsigned int i) const {%(argument_name_function_body)s}
|
||||
virtual Argument* getArgument(unsigned int i) const { return entity->getArgument(i); }
|
||||
%(inverse)s bool is(Type::Enum v) const;
|
||||
|
||||
@@ -100,8 +100,8 @@
|
||||
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
|
||||
#include <TopTools_ListIteratorOfListOfShape.hxx>
|
||||
|
||||
#include "../ifcparse/IfcSIPrefix.h"
|
||||
#include "../ifcgeom/IfcGeom.h"
|
||||
#include "../ifcgeom/IfcGeomUtils.h"
|
||||
|
||||
bool IfcGeom::Kernel::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) {
|
||||
BRepOffsetAPI_Sewing builder;
|
||||
@@ -1015,7 +1015,7 @@ std::pair<std::string, double> IfcGeom::Kernel::initializeUnits(IfcSchema::IfcUn
|
||||
}
|
||||
if ( unit ) {
|
||||
if ( unit->hasPrefix() ) {
|
||||
value *= IfcGeom::Utils::UnitPrefixToValue(unit->Prefix());
|
||||
value *= IfcParse::IfcSIPrefixToValue(unit->Prefix());
|
||||
}
|
||||
IfcSchema::IfcUnitEnum::IfcUnitEnum type = unit->UnitType();
|
||||
if ( type == IfcSchema::IfcUnitEnum::IfcUnit_LENGTHUNIT ) {
|
||||
|
||||
@@ -88,8 +88,14 @@ class file(object):
|
||||
return entity_instance(self.wrapped_data.by_id(key))
|
||||
elif isinstance(key, str):
|
||||
return entity_instance(self.wrapped_data.by_guid(key))
|
||||
def add(self, inst):
|
||||
return entity_instance(self.wrapped_data.add(inst.wrapped_data))
|
||||
def by_type(self, type):
|
||||
return [entity_instance(e) for e in self.wrapped_data.by_type(type)]
|
||||
def traverse(self, inst):
|
||||
return [entity_instance(e) for e in self.wrapped_data.traverse(inst.wrapped_data)]
|
||||
def remove(self, inst):
|
||||
return self.wrapped_data.remove(inst.wrapped_data)
|
||||
def __iter__(self):
|
||||
return iter(self[id] for id in self.wrapped_data.entity_names())
|
||||
|
||||
|
||||
+1148
-1152
File diff suppressed because it is too large
Load Diff
@@ -38,12 +38,12 @@ namespace Type {
|
||||
int GetAttributeCount(Enum t);
|
||||
int GetAttributeIndex(Enum t, const std::string& a);
|
||||
IfcUtil::ArgumentType GetAttributeType(Enum t, unsigned char a);
|
||||
Enum GetAttributeEntity(Enum t, unsigned char a);
|
||||
const std::string& GetAttributeName(Enum t, unsigned char a);
|
||||
bool GetAttributeOptional(Enum t, unsigned char a);
|
||||
bool GetAttributeDerived(Enum t, unsigned char a);
|
||||
std::pair<const char*, int> GetEnumerationIndex(Enum t, const std::string& a);
|
||||
std::pair<Enum, unsigned> GetInverseAttribute(Enum t, const std::string& a);
|
||||
Enum GetAttributeEnumerationClass(Enum t, unsigned char a);
|
||||
void PopulateDerivedFields(IfcWrite::IfcWritableEntity* e);
|
||||
}}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
+1136
-1140
File diff suppressed because it is too large
Load Diff
@@ -38,12 +38,12 @@ namespace Type {
|
||||
int GetAttributeCount(Enum t);
|
||||
int GetAttributeIndex(Enum t, const std::string& a);
|
||||
IfcUtil::ArgumentType GetAttributeType(Enum t, unsigned char a);
|
||||
Enum GetAttributeEntity(Enum t, unsigned char a);
|
||||
const std::string& GetAttributeName(Enum t, unsigned char a);
|
||||
bool GetAttributeOptional(Enum t, unsigned char a);
|
||||
bool GetAttributeDerived(Enum t, unsigned char a);
|
||||
std::pair<const char*, int> GetEnumerationIndex(Enum t, const std::string& a);
|
||||
std::pair<Enum, unsigned> GetInverseAttribute(Enum t, const std::string& a);
|
||||
Enum GetAttributeEnumerationClass(Enum t, unsigned char a);
|
||||
void PopulateDerivedFields(IfcWrite::IfcWritableEntity* e);
|
||||
}}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -87,7 +87,7 @@ namespace IfcUtil {
|
||||
public:
|
||||
IfcEntityDescriptor(IfcSchema::Type::Enum type, IfcEntityDescriptor* parent)
|
||||
: type(type), parent(parent) {}
|
||||
void add(const std::string& name, bool optional, ArgumentType argument_type, IfcSchema::Type::Enum data_type = IfcSchema::Type::ALL) {
|
||||
void add(const std::string& name, bool optional, ArgumentType argument_type, IfcSchema::Type::Enum data_type = IfcSchema::Type::UNDEFINED) {
|
||||
arguments.push_back(IfcArgumentDescriptor(name, optional, argument_type, data_type));
|
||||
}
|
||||
unsigned getArgumentCount() const {
|
||||
@@ -111,10 +111,10 @@ namespace IfcUtil {
|
||||
? parent->getArgumentOptional(i)
|
||||
: get_argument(i-a).optional;
|
||||
}
|
||||
IfcSchema::Type::Enum getArgumentEnumerationClass(unsigned i) const {
|
||||
IfcSchema::Type::Enum getArgumentEntity(unsigned i) const {
|
||||
const unsigned a = argument_start();
|
||||
return i < a
|
||||
? parent->getArgumentEnumerationClass(i)
|
||||
? parent->getArgumentEntity(i)
|
||||
: get_argument(i-a).data_type;
|
||||
}
|
||||
unsigned getArgumentIndex(const std::string& s) const {
|
||||
|
||||
+16
-1
@@ -21,6 +21,7 @@
|
||||
#define IFCFILE_H
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
#include "../ifcparse/IfcSpfHeader.h"
|
||||
@@ -38,6 +39,8 @@ public:
|
||||
typedef std::map<unsigned int, unsigned int> offset_by_id_t;
|
||||
typedef entity_by_id_t::const_iterator const_iterator;
|
||||
private:
|
||||
typedef std::map<IfcUtil::IfcBaseClass*, IfcUtil::IfcBaseClass*> entity_entity_map_t;
|
||||
|
||||
bool _create_latebound_entities;
|
||||
|
||||
entity_by_id_t byid;
|
||||
@@ -46,12 +49,15 @@ private:
|
||||
entity_by_guid_t byguid;
|
||||
offset_by_id_t offsets;
|
||||
|
||||
entity_entity_map_t entity_file_map;
|
||||
|
||||
unsigned int lastId;
|
||||
unsigned int MaxId;
|
||||
|
||||
IfcSpfHeader _header;
|
||||
|
||||
void setDefaultHeaderValues();
|
||||
void traverse(IfcUtil::IfcBaseClass*, std::set<IfcUtil::IfcBaseClass*>& visited, IfcEntityList::ptr list, int level, int max_level);
|
||||
public:
|
||||
IfcParse::IfcSpfLexer* tokens;
|
||||
IfcParse::IfcSpfStream* stream;
|
||||
@@ -96,6 +102,11 @@ public:
|
||||
/// Returns the entity with the specified GlobalId
|
||||
IfcSchema::IfcRoot* EntityByGuid(const std::string& guid);
|
||||
|
||||
/// Performs a depth-first traversal, returning all entity instance
|
||||
/// attributes as a flat list. NB: includes the root instance specified
|
||||
/// in the first function argument.
|
||||
IfcEntityList::ptr traverse(IfcUtil::IfcBaseClass* instance, int max_level=-1);
|
||||
|
||||
bool Init(const std::string& fn);
|
||||
bool Init(std::istream& fn, int len);
|
||||
bool Init(void* data, int len);
|
||||
@@ -105,15 +116,19 @@ public:
|
||||
|
||||
unsigned int FreshId() { return ++MaxId; }
|
||||
|
||||
void AddEntity(IfcUtil::IfcBaseClass* entity);
|
||||
IfcUtil::IfcBaseClass* AddEntity(IfcUtil::IfcBaseClass* entity);
|
||||
void AddEntities(IfcEntityList::ptr es);
|
||||
|
||||
void removeEntity(IfcUtil::IfcBaseClass* entity);
|
||||
|
||||
const IfcSpfHeader& header() const { return _header; }
|
||||
IfcSpfHeader& header() { return _header; }
|
||||
|
||||
std::string createTimestamp() const;
|
||||
|
||||
bool create_latebound_entities() const { return _create_latebound_entities; }
|
||||
|
||||
std::pair<IfcSchema::IfcNamedUnit*, double> getUnit(IfcSchema::IfcUnitEnum::IfcUnitEnum);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ IfcSchema::IfcProject* IfcHierarchyHelper::addProject(IfcSchema::IfcOwnerHistory
|
||||
IfcSchema::IfcSIUnit* unit2a = new IfcSchema::IfcSIUnit(IfcSchema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT,
|
||||
boost::none, IfcSchema::IfcSIUnitName::IfcSIUnitName_RADIAN);
|
||||
IfcSchema::IfcMeasureWithUnit* unit2b = new IfcSchema::IfcMeasureWithUnit(
|
||||
new IfcWrite::IfcSelectHelper(0.017453293, IfcSchema::Type::IfcPlaneAngleMeasure), unit2a);
|
||||
new IfcSchema::IfcPlaneAngleMeasure(0.017453293), unit2a);
|
||||
IfcSchema::IfcConversionBasedUnit* unit2 = new IfcSchema::IfcConversionBasedUnit(dimexp,
|
||||
IfcSchema::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT, "Degrees", unit2b);
|
||||
|
||||
|
||||
@@ -89,6 +89,9 @@ IfcUtil::ArgumentType IfcParse::IfcLateBoundEntity::getArgumentType(unsigned int
|
||||
? IfcUtil::Argument_DERIVED
|
||||
: IfcSchema::Type::GetAttributeType(_type,i);
|
||||
}
|
||||
IfcSchema::Type::Enum IfcParse::IfcLateBoundEntity::getArgumentEntity(unsigned int i) const {
|
||||
return IfcSchema::Type::GetAttributeEntity(_type, i);
|
||||
}
|
||||
Argument* IfcParse::IfcLateBoundEntity::getArgument(unsigned int i) const {
|
||||
return entity->getArgument(i);
|
||||
}
|
||||
@@ -134,7 +137,7 @@ void IfcParse::IfcLateBoundEntity::setArgument(unsigned int i, const std::string
|
||||
if (arg_type == Argument_STRING) {
|
||||
writable_entity()->setArgument(i,a);
|
||||
} else if (arg_type == Argument_ENUMERATION) {
|
||||
std::pair<const char*, int> enum_data = IfcSchema::Type::GetEnumerationIndex(IfcSchema::Type::GetAttributeEnumerationClass(_type, i), a);
|
||||
std::pair<const char*, int> enum_data = IfcSchema::Type::GetEnumerationIndex(IfcSchema::Type::GetAttributeEntity(_type, i), a);
|
||||
writable_entity()->setArgument(i, enum_data.second, enum_data.first);
|
||||
} else invalid_argument(i,"STRING");
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ namespace IfcParse {
|
||||
unsigned int id() const;
|
||||
unsigned int getArgumentCount() const;
|
||||
IfcUtil::ArgumentType getArgumentType(unsigned int i) const;
|
||||
IfcSchema::Type::Enum getArgumentEntity(unsigned int i) const;
|
||||
Argument* getArgument(unsigned int i) const;
|
||||
const char* getArgumentName(unsigned int i) const;
|
||||
unsigned getArgumentIndex(const std::string& a) const;
|
||||
|
||||
+314
-54
@@ -17,6 +17,7 @@
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
@@ -35,6 +36,7 @@
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
#include "../ifcparse/IfcLateBoundEntity.h"
|
||||
#include "../ifcparse/IfcFile.h"
|
||||
#include "../ifcparse/IfcSIPrefix.h"
|
||||
|
||||
using namespace IfcParse;
|
||||
|
||||
@@ -804,12 +806,15 @@ IfcFile::IfcFile(bool create_latebound_entities)
|
||||
bool IfcFile::Init(const std::string& fn) {
|
||||
return IfcFile::Init(new IfcSpfStream(fn));
|
||||
}
|
||||
|
||||
bool IfcFile::Init(std::istream& f, int len) {
|
||||
return IfcFile::Init(new IfcSpfStream(f,len));
|
||||
}
|
||||
|
||||
bool IfcFile::Init(void* data, int len) {
|
||||
return IfcFile::Init(new IfcSpfStream(data,len));
|
||||
}
|
||||
|
||||
bool IfcFile::Init(IfcParse::IfcSpfStream* s) {
|
||||
// Initialize a "C" locale for locale-independent
|
||||
// number parsing. See comment above on line 41.
|
||||
@@ -920,13 +925,142 @@ bool IfcFile::Init(IfcParse::IfcSpfStream* s) {
|
||||
Logger::Status("\rDone scanning file ");
|
||||
return true;
|
||||
}
|
||||
|
||||
void IfcFile::traverse(IfcUtil::IfcBaseClass* instance, std::set<IfcUtil::IfcBaseClass*>& visited, IfcEntityList::ptr list, int level, int max_level) {
|
||||
if (visited.find(instance) != visited.end()) {
|
||||
return;
|
||||
}
|
||||
visited.insert(instance);
|
||||
list->push(instance);
|
||||
|
||||
if (level >= max_level && max_level > 0) return;
|
||||
|
||||
for (unsigned i = 0; i < instance->getArgumentCount(); ++i) {
|
||||
Argument* arg = instance->getArgument(i);
|
||||
|
||||
if (arg->type() == IfcUtil::Argument_ENTITY) {
|
||||
traverse(*arg, visited, list, level + 1, max_level);
|
||||
} else if (arg->type() == IfcUtil::Argument_ENTITY_LIST) {
|
||||
IfcEntityList::ptr entity_list_attribute = *arg;
|
||||
for (IfcEntityList::it it = entity_list_attribute->begin(); it != entity_list_attribute->end(); ++it) {
|
||||
traverse(*it, visited, list, level + 1, max_level);
|
||||
}
|
||||
} else if (arg->type() == IfcUtil::Argument_ENTITY_LIST_LIST) {
|
||||
IfcEntityListList::ptr entity_list_attribute = *arg;
|
||||
for (IfcEntityListList::outer_it it = entity_list_attribute->begin(); it != entity_list_attribute->end(); ++it) {
|
||||
for (IfcEntityListList::inner_it jt = it->begin(); jt != it->end(); ++jt) {
|
||||
traverse(*jt, visited, list, level + 1, max_level);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IfcEntityList::ptr IfcFile::traverse(IfcUtil::IfcBaseClass* instance, int max_level) {
|
||||
std::set<IfcUtil::IfcBaseClass*> visited;
|
||||
IfcEntityList::ptr return_value(new IfcEntityList);
|
||||
traverse(instance, visited, return_value, 0, max_level);
|
||||
return return_value;
|
||||
}
|
||||
|
||||
void IfcFile::AddEntities(IfcEntityList::ptr es) {
|
||||
for( IfcEntityList::it i = es->begin(); i != es->end(); ++ i ) {
|
||||
AddEntity(*i);
|
||||
}
|
||||
}
|
||||
void IfcFile::AddEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
if ( entity->is(IfcSchema::Type::IfcRoot) ) {
|
||||
|
||||
IfcUtil::IfcBaseClass* IfcFile::AddEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
// 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);
|
||||
if (it != entity_file_map.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Obtain all forward references by a depth-first
|
||||
// traversal and add them to the file.
|
||||
{ IfcEntityList::ptr entity_attributes = traverse(entity, 1);
|
||||
for (IfcEntityList::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) {
|
||||
if (*it != entity) {
|
||||
entity_file_map.insert(entity_entity_map_t::value_type(*it, AddEntity(*it)));
|
||||
}
|
||||
} }
|
||||
|
||||
// See whether the instance is already part of a file
|
||||
if (entity->entity->file != 0) {
|
||||
if (entity->entity->file == this) {
|
||||
// If it is part of this file
|
||||
// nothing needs to be done.
|
||||
return entity;
|
||||
}
|
||||
|
||||
// An instance is being added from another file. A copy of the
|
||||
// container and entity 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);
|
||||
if (this->create_latebound_entities()) {
|
||||
entity = new IfcLateBoundEntity(we);
|
||||
} else {
|
||||
entity = IfcSchema::SchemaEntity(we);
|
||||
}
|
||||
|
||||
// In case an entity is added that contains geometry, the unit
|
||||
// information needs to be accounted for for IfcLengthMeasures.
|
||||
boost::optional<double> conversion_factor;
|
||||
|
||||
for (unsigned i = 0; i < we->getArgumentCount(); ++i) {
|
||||
Argument* attr = we->getArgument(i);
|
||||
IfcUtil::ArgumentType attr_type = attr->type();
|
||||
if (attr_type == IfcUtil::Argument_ENTITY) {
|
||||
we->setArgument(i, entity_file_map[*attr]);
|
||||
} else if (attr_type == IfcUtil::Argument_ENTITY_LIST) {
|
||||
IfcEntityList::ptr instances = *attr;
|
||||
IfcEntityList::ptr new_instances(new IfcEntityList);
|
||||
for (IfcEntityList::it it = instances->begin(); it != instances->end(); ++it) {
|
||||
new_instances->push(entity_file_map[*it]);
|
||||
}
|
||||
we->setArgument(i, new_instances);
|
||||
} else if (attr_type == IfcUtil::Argument_ENTITY_LIST_LIST) {
|
||||
IfcEntityListList::ptr instances = *attr;
|
||||
IfcEntityListList::ptr new_instances(new IfcEntityListList);
|
||||
for (IfcEntityListList::outer_it it = instances->begin(); it != instances->end(); ++it) {
|
||||
std::vector<IfcUtil::IfcBaseClass*> list;
|
||||
for (IfcEntityListList::inner_it jt = it->begin(); jt != it->end(); ++jt) {
|
||||
list.push_back(entity_file_map[*jt]);
|
||||
}
|
||||
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_VECTOR_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A new entity instance name is generated and
|
||||
// the instance is pointed to this file.
|
||||
we->file = this;
|
||||
we->setId(FreshId());
|
||||
}
|
||||
|
||||
// For subtypes of IfcRoot, the GUID mapping needs to be updated.
|
||||
if (entity->is(IfcSchema::Type::IfcRoot)) {
|
||||
IfcSchema::IfcRoot* ifc_root = (IfcSchema::IfcRoot*) entity;
|
||||
try {
|
||||
const std::string guid = ifc_root->GlobalId();
|
||||
@@ -941,6 +1075,7 @@ void IfcFile::AddEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
}
|
||||
}
|
||||
|
||||
// The mapping by entity type is updated.
|
||||
IfcSchema::Type::Enum ty = entity->type();
|
||||
do {
|
||||
IfcEntityList::ptr instances_by_type = EntitiesByType(ty);
|
||||
@@ -953,92 +1088,181 @@ void IfcFile::AddEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
} while ( ty > -1 );
|
||||
|
||||
int new_id = -1;
|
||||
// For newly created entities ensure a valid ENTITY_INSTANCE_NAME is set
|
||||
if ( entity->entity->isWritable() ) {
|
||||
if ( ! entity->entity->file ) entity->entity->file = this;
|
||||
if (entity->entity->isWritable() && !entity->entity->file) {
|
||||
// For newly created entities ensure a valid ENTITY_INSTANCE_NAME is set
|
||||
entity->entity->file = this;
|
||||
new_id = entity->entity->isWritable()->setId();
|
||||
} else {
|
||||
// TODO: Detect and fix ENTITY_INSTANCE_NAME collisions
|
||||
new_id = entity->entity->id();
|
||||
}
|
||||
if ( byid.find(new_id) != byid.end() ) {
|
||||
|
||||
if (byid.find(new_id) != byid.end()) {
|
||||
// This should not happen
|
||||
std::stringstream ss;
|
||||
ss << "Overwriting entity with id " << new_id;
|
||||
Logger::Message(Logger::LOG_WARNING,ss.str());
|
||||
Logger::Message(Logger::LOG_WARNING, ss.str());
|
||||
}
|
||||
|
||||
// The mapping by entity instance name is updated.
|
||||
byid[new_id] = entity;
|
||||
|
||||
unsigned arg_count = entity->entity->getArgumentCount();
|
||||
for (unsigned i = 0; i < arg_count; ++i) {
|
||||
Argument* arg = entity->entity->getArgument(i);
|
||||
// The mapping by reference is updated.
|
||||
IfcEntityList::ptr entity_attributes = traverse(entity, 1);
|
||||
for (IfcEntityList::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) {
|
||||
IfcUtil::IfcBaseClass* entity_attribute = *it;
|
||||
try {
|
||||
if (!IfcSchema::Type::IsSimple(entity_attribute->type())) {
|
||||
unsigned entity_attribute_id = entity_attribute->entity->id();
|
||||
IfcEntityList::ptr refs = EntitiesByReference(entity_attribute_id);
|
||||
if (!refs) {
|
||||
refs = IfcEntityList::ptr(new IfcEntityList);
|
||||
byref[entity_attribute_id] = refs;
|
||||
}
|
||||
refs->push(entity);
|
||||
}
|
||||
} catch (IfcParse::IfcException&) {}
|
||||
}
|
||||
|
||||
// Create a flat list of entity instances referenced by the instance that is being added
|
||||
IfcEntityList::ptr entity_attributes(new IfcEntityList);
|
||||
if (arg->type() == IfcUtil::Argument_ENTITY) {
|
||||
IfcUtil::IfcBaseClass* entity_attribute = *arg;
|
||||
entity_attributes->push(entity_attribute);
|
||||
} else if (arg->type() == IfcUtil::Argument_ENTITY_LIST) {
|
||||
IfcEntityList::ptr entity_list_attribute = *arg;
|
||||
entity_attributes->push(entity_list_attribute);
|
||||
} else if (arg->type() == IfcUtil::Argument_ENTITY_LIST_LIST) {
|
||||
IfcEntityListList::ptr entity_list_attribute = *arg;
|
||||
for (IfcEntityListList::outer_it it = entity_list_attribute->begin(); it != entity_list_attribute->end(); ++it) {
|
||||
for (IfcEntityListList::inner_it jt = it->begin(); jt != it->end(); ++jt) {
|
||||
entity_attributes->push(*jt);
|
||||
return entity;
|
||||
}
|
||||
|
||||
IfcWrite::IfcWritableEntity* make_writable(IfcUtil::IfcBaseClass* instance) {
|
||||
if (instance->entity->isWritable()) {
|
||||
return instance->entity->isWritable();
|
||||
}
|
||||
|
||||
IfcWrite::IfcWritableEntity* return_value;
|
||||
instance->entity = return_value = new IfcWrite::IfcWritableEntity(instance->entity);
|
||||
return return_value;
|
||||
}
|
||||
|
||||
void IfcFile::removeEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
const unsigned id = entity->entity->id();
|
||||
IfcUtil::IfcBaseClass* file_entity = 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
|
||||
// individual IfcRepresentationItems can not be deleted if an IfcStyledItem is
|
||||
// related. Hence, the IfcRepresentationItem::StyledByItem relation could be
|
||||
// characterized as weak.
|
||||
std::set<IfcSchema::Type::Enum> weak_roots;
|
||||
|
||||
if (entity != file_entity) {
|
||||
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
|
||||
// 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.
|
||||
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);
|
||||
if (attr->isNull()) continue;
|
||||
|
||||
IfcUtil::ArgumentType attr_type = related_instance->getArgumentType(i);
|
||||
switch(attr_type) {
|
||||
case IfcUtil::Argument_ENTITY: {
|
||||
IfcUtil::IfcBaseClass* instance_attribute = *attr;
|
||||
if (instance_attribute == entity) {
|
||||
make_writable(related_instance)->setArgument(i);
|
||||
// deletion_queue.insert(related_instance);
|
||||
} }
|
||||
break;
|
||||
case IfcUtil::Argument_ENTITY_LIST: {
|
||||
IfcEntityList::ptr instance_list = *attr;
|
||||
if (instance_list->contains(entity)) {
|
||||
instance_list->remove(entity);
|
||||
make_writable(related_instance)->setArgument(i, instance_list);
|
||||
/* if (instance_list->size() == 0) {
|
||||
deletion_queue.insert(related_instance);
|
||||
} */
|
||||
} }
|
||||
break;
|
||||
case IfcUtil::Argument_ENTITY_LIST_LIST: {
|
||||
IfcEntityListList::ptr instance_list_list = *attr;
|
||||
if (instance_list_list->contains(entity)) {
|
||||
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*>::const_iterator jt;
|
||||
while ((jt = std::find(instances.begin(), instances.end(), entity)) != instances.end()) {
|
||||
instances.erase(jt);
|
||||
}
|
||||
new_list->push(instances);
|
||||
}
|
||||
make_writable(related_instance)->setArgument(i, new_list);
|
||||
/* if (new_list->totalSize() == 0) {
|
||||
deletion_queue.insert(related_instance);
|
||||
} */
|
||||
} }
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
byref.erase(byref.find(id));
|
||||
}
|
||||
|
||||
for (IfcEntityList::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) {
|
||||
IfcUtil::IfcBaseClass* entity_attribute = *it;
|
||||
try {
|
||||
if (!IfcSchema::Type::IsSimple(entity_attribute->type())) {
|
||||
// At this point simple types are IfcSelectHelper instances
|
||||
// which are not writable and do not have an instance name.
|
||||
if (entity_attribute->entity->isWritable()) {
|
||||
if ( ! entity_attribute->entity->file ) {
|
||||
entity_attribute->entity->file = this;
|
||||
}
|
||||
entity_attribute->entity->isWritable()->setId();
|
||||
}
|
||||
unsigned entity_attribute_id = entity_attribute->entity->id();
|
||||
IfcEntityList::ptr refs = EntitiesByReference(entity_attribute_id);
|
||||
if (!refs) {
|
||||
refs = IfcEntityList::ptr(new IfcEntityList);
|
||||
byref[entity_attribute_id] = refs;
|
||||
}
|
||||
refs->push(entity);
|
||||
}
|
||||
} catch (IfcParse::IfcException&) {}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (entity->is(IfcSchema::Type::IfcRoot)) {
|
||||
const std::string global_id = ((IfcSchema::IfcRoot*) entity)->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);
|
||||
|
||||
while (!deletion_queue.empty()) {
|
||||
removeEntity(*deletion_queue.begin());
|
||||
deletion_queue.erase(deletion_queue.begin());
|
||||
}
|
||||
|
||||
delete entity->entity;
|
||||
delete entity;
|
||||
}
|
||||
|
||||
IfcEntityList::ptr IfcFile::EntitiesByType(IfcSchema::Type::Enum t) {
|
||||
entities_by_type_t::const_iterator it = bytype.find(t);
|
||||
return (it == bytype.end()) ? IfcEntityList::ptr() : it->second;
|
||||
}
|
||||
|
||||
IfcEntityList::ptr IfcFile::EntitiesByType(const std::string& t) {
|
||||
std::string ty = t;
|
||||
for (std::string::iterator p = ty.begin(); p != ty.end(); ++p ) *p = toupper(*p);
|
||||
return EntitiesByType(IfcSchema::Type::FromString(ty));
|
||||
}
|
||||
|
||||
IfcEntityList::ptr IfcFile::EntitiesByReference(int t) {
|
||||
entities_by_ref_t::const_iterator it = byref.find(t);
|
||||
return (it == byref.end()) ? IfcEntityList::ptr() : it->second;
|
||||
}
|
||||
|
||||
IfcUtil::IfcBaseClass* IfcFile::EntityById(int id) {
|
||||
entity_by_id_t::const_iterator it = byid.find(id);
|
||||
if ( it == byid.end() ) {
|
||||
offset_by_id_t::const_iterator it2 = offsets.find(id);
|
||||
if ( it2 == offsets.end() ) throw IfcException("Entity not found");
|
||||
const unsigned int offset = (*it2).second;
|
||||
Entity* e = new Entity(id,this,offset);
|
||||
IfcUtil::IfcBaseClass* entity = IfcSchema::SchemaEntity(e);
|
||||
byid[id] = entity;
|
||||
return entity;
|
||||
if (it == byid.end()) {
|
||||
throw IfcException("Entity not found");
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
IfcSchema::IfcRoot* IfcFile::EntityByGuid(const std::string& guid) {
|
||||
entity_by_guid_t::const_iterator it = byguid.find(guid);
|
||||
if ( it == byguid.end() ) {
|
||||
@@ -1065,6 +1289,7 @@ IfcFile::~IfcFile() {
|
||||
IfcFile::entity_by_id_t::const_iterator IfcFile::begin() const {
|
||||
return byid.begin();
|
||||
}
|
||||
|
||||
IfcFile::entity_by_id_t::const_iterator IfcFile::end() const {
|
||||
return byid.end();
|
||||
}
|
||||
@@ -1109,7 +1334,7 @@ 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::ALL || (*it)->is(type);
|
||||
bool valid = type == IfcSchema::Type::UNDEFINED || (*it)->is(type);
|
||||
if (valid && attribute_index >= 0) {
|
||||
Argument* arg = (*it)->entity->getArgument(attribute_index);
|
||||
if (arg->type() == IfcUtil::Argument_ENTITY) {
|
||||
@@ -1151,3 +1376,38 @@ void IfcFile::setDefaultHeaderValues() {
|
||||
header().file_schema().schema_identifiers(schema_identifiers);
|
||||
}
|
||||
|
||||
std::pair<IfcSchema::IfcNamedUnit*, double> IfcFile::getUnit(IfcSchema::IfcUnitEnum::IfcUnitEnum type) {
|
||||
std::pair<IfcSchema::IfcNamedUnit*, double> return_value((IfcSchema::IfcNamedUnit*)0, 1.);
|
||||
IfcSchema::IfcProject::list::ptr projects = EntitiesByType<IfcSchema::IfcProject>();
|
||||
if (projects->size() == 1) {
|
||||
IfcSchema::IfcProject* project = *projects->begin();
|
||||
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)) {
|
||||
IfcSchema::IfcNamedUnit* named_unit = (IfcSchema::IfcNamedUnit*) unit;
|
||||
if (named_unit->UnitType() != type) {
|
||||
continue;
|
||||
}
|
||||
IfcSchema::IfcSIUnit* unit = 0;
|
||||
if (named_unit->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.first = named_unit;
|
||||
if (mu->UnitComponent()->is(IfcSchema::Type::IfcSIUnit)) {
|
||||
unit = (IfcSchema::IfcSIUnit*) mu->UnitComponent();
|
||||
}
|
||||
} else if (named_unit->is(IfcSchema::Type::IfcSIUnit)) {
|
||||
return_value.first = unit = (IfcSchema::IfcSIUnit*) named_unit;
|
||||
}
|
||||
if (unit) {
|
||||
if (unit->hasPrefix()) {
|
||||
return_value.second *= IfcSIPrefixToValue(unit->Prefix());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
@@ -16,12 +16,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
#include "IfcSIPrefix.h"
|
||||
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
|
||||
#include "IfcGeomUtils.h"
|
||||
|
||||
double IfcGeom::Utils::UnitPrefixToValue( IfcSchema::IfcSIPrefix::IfcSIPrefix v ) {
|
||||
double IfcParse::IfcSIPrefixToValue(IfcSchema::IfcSIPrefix::IfcSIPrefix v) {
|
||||
if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_EXA ) return 1.e18;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_PETA ) return 1.e15;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_TERA ) return 1.e12;
|
||||
@@ -38,5 +35,5 @@ double IfcGeom::Utils::UnitPrefixToValue( IfcSchema::IfcSIPrefix::IfcSIPrefix v
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_PICO ) return 1.e-12;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_FEMTO ) return 1.e-15;
|
||||
else if ( v == IfcSchema::IfcSIPrefix::IfcSIPrefix_ATTO ) return 1.e-18;
|
||||
else return 1.f;
|
||||
else return 1.;
|
||||
}
|
||||
@@ -17,14 +17,13 @@
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCGEOMUTILS_H
|
||||
#define IFCGEOMUTILS_H
|
||||
#ifndef IFCSIPREFIX
|
||||
#define IFCSIPREFIX
|
||||
|
||||
namespace IfcGeom {
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
|
||||
namespace Utils {
|
||||
double UnitPrefixToValue(IfcSchema::IfcSIPrefix::IfcSIPrefix v);
|
||||
}
|
||||
namespace IfcParse {
|
||||
double IfcSIPrefixToValue(IfcSchema::IfcSIPrefix::IfcSIPrefix v);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -41,6 +41,29 @@ IfcUtil::IfcBaseClass* IfcEntityList::operator[] (int i) {
|
||||
bool IfcEntityList::contains(IfcUtil::IfcBaseClass* instance) const {
|
||||
return std::find(ls.begin(), ls.end(), instance) != ls.end();
|
||||
}
|
||||
void IfcEntityList::remove(IfcUtil::IfcBaseClass* instance) {
|
||||
std::vector<IfcUtil::IfcBaseClass*>::const_iterator it;
|
||||
while ((it = std::find(ls.begin(), ls.end(), instance)) != ls.end()) {
|
||||
ls.erase(it);
|
||||
}
|
||||
}
|
||||
IfcEntityList::ptr IfcEntityList::filtered(const std::set<IfcSchema::Type::Enum>& entities) {
|
||||
IfcEntityList::ptr return_value(new IfcEntityList);
|
||||
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)) {
|
||||
contained = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!contained) {
|
||||
return_value->push(*it);
|
||||
}
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
|
||||
|
||||
unsigned int IfcUtil::IfcBaseType::getArgumentCount() const { return 1; }
|
||||
Argument* IfcUtil::IfcBaseType::getArgument(unsigned int i) const { return entity->getArgument(i); }
|
||||
|
||||
+33
-9
@@ -20,6 +20,7 @@
|
||||
#ifndef IFCUTIL_H
|
||||
#define IFCUTIL_H
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
@@ -66,22 +67,23 @@ namespace IfcUtil {
|
||||
IfcAbstractEntity* entity;
|
||||
virtual bool is(IfcSchema::Type::Enum v) const = 0;
|
||||
virtual IfcSchema::Type::Enum type() const = 0;
|
||||
};
|
||||
|
||||
class IfcBaseEntity : public IfcBaseClass {
|
||||
public:
|
||||
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;
|
||||
};
|
||||
|
||||
class IfcBaseEntity : public IfcBaseClass {
|
||||
};
|
||||
|
||||
// TODO: Investigate whether these should be template classes instead
|
||||
class IfcBaseType : public IfcBaseEntity {
|
||||
public:
|
||||
virtual unsigned int getArgumentCount() const;
|
||||
virtual Argument* getArgument(unsigned int i) const;
|
||||
virtual const char* getArgumentName(unsigned int i) const;
|
||||
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; }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -103,10 +105,12 @@ public:
|
||||
template <class U>
|
||||
typename U::list::ptr as() {
|
||||
typename U::list::ptr r(new typename U::list);
|
||||
const bool all = U::Class() == IfcSchema::Type::ALL;
|
||||
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);
|
||||
return r;
|
||||
}
|
||||
void remove(IfcUtil::IfcBaseClass*);
|
||||
IfcEntityList::ptr filtered(const std::set<IfcSchema::Type::Enum>& entities);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@@ -133,6 +137,12 @@ public:
|
||||
for ( it i = begin(); i != end(); ++ i ) if (all || (*i)->is(U::Class())) r->push((U*)*i);
|
||||
return r;
|
||||
}
|
||||
void remove(T* t) {
|
||||
typename std::vector<T*>::const_iterator it;
|
||||
while ((it = std::find(ls.begin(), ls.end(), t)) != ls.end()) {
|
||||
ls.erase(it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@@ -157,6 +167,13 @@ public:
|
||||
outer_it begin() const { return ls.begin(); }
|
||||
outer_it end() const { return ls.end(); }
|
||||
int size() const { return ls.size(); }
|
||||
int totalSize() const {
|
||||
int accum = 0;
|
||||
for (outer_it it = begin(); it != end(); ++it) {
|
||||
accum += it->size();
|
||||
}
|
||||
return accum;
|
||||
}
|
||||
bool contains(IfcUtil::IfcBaseClass* instance) const {
|
||||
for (outer_it it = begin(); it != end(); ++it) {
|
||||
const std::vector<IfcUtil::IfcBaseClass*>& inner = *it;
|
||||
@@ -192,7 +209,14 @@ public:
|
||||
void push(const std::vector<T*>& t) {ls.push_back(t);}
|
||||
outer_it begin() { return ls.begin(); }
|
||||
outer_it end() { return ls.end(); }
|
||||
unsigned int size() const { return (unsigned int) ls.size(); }
|
||||
int size() const { return ls.size(); }
|
||||
int totalSize() const {
|
||||
int accum = 0;
|
||||
for (outer_it it = begin(); it != end(); ++it) {
|
||||
accum += it->size();
|
||||
}
|
||||
return accum;
|
||||
}
|
||||
bool contains(T* t) const {
|
||||
for (outer_it it = begin(); it != end(); ++it) {
|
||||
const std::vector<T*>& inner = *it;
|
||||
|
||||
@@ -341,55 +341,6 @@ IfcUtil::ArgumentType IfcWriteArgument::type() const {
|
||||
return static_cast<IfcUtil::ArgumentType>(container.which());
|
||||
}
|
||||
|
||||
IfcEntityList::ptr IfcSelectHelperEntity::getInverse(IfcSchema::Type::Enum, int) {throw IfcParse::IfcException("Invalid cast");}
|
||||
std::string IfcSelectHelperEntity::datatype() const { return IfcSchema::Type::ToString(_type); }
|
||||
Argument* IfcSelectHelperEntity::getArgument(unsigned int i) {
|
||||
if ( i != 0 ) throw IfcParse::IfcException("Invalid cast");
|
||||
return arg;
|
||||
}
|
||||
unsigned int IfcSelectHelperEntity::getArgumentCount() const { return 1; }
|
||||
IfcSchema::Type::Enum IfcSelectHelperEntity::type() const { return _type; }
|
||||
bool IfcSelectHelperEntity::is(IfcSchema::Type::Enum t) const { return _type == t; }
|
||||
std::string IfcSelectHelperEntity::toString(bool upper) const {
|
||||
std::stringstream ss;
|
||||
std::string dt = datatype();
|
||||
if ( upper ) {
|
||||
for (std::string::iterator p = dt.begin(); p != dt.end(); ++p ) *p = toupper(*p);
|
||||
}
|
||||
ss << dt << "(" << arg->toString(upper) << ")";
|
||||
return ss.str();
|
||||
}
|
||||
unsigned int IfcSelectHelperEntity::id() { throw IfcParse::IfcException("Invalid cast"); }
|
||||
IfcWrite::IfcWritableEntity* IfcSelectHelperEntity::isWritable() { throw IfcParse::IfcException("Invalid cast"); }
|
||||
|
||||
IfcSelectHelper::IfcSelectHelper(const std::string& v, IfcSchema::Type::Enum t) {
|
||||
IfcWriteArgument* a = new IfcWriteArgument(0);
|
||||
a->set(v);
|
||||
this->entity = new IfcSelectHelperEntity(t,a);
|
||||
}
|
||||
IfcSelectHelper::IfcSelectHelper(const char* const v, IfcSchema::Type::Enum t) {
|
||||
IfcWriteArgument* a = new IfcWriteArgument(0);
|
||||
a->set<std::string>(v);
|
||||
this->entity = new IfcSelectHelperEntity(t,a);
|
||||
}
|
||||
IfcSelectHelper::IfcSelectHelper(int v, IfcSchema::Type::Enum t) {
|
||||
IfcWriteArgument* a = new IfcWriteArgument(0);
|
||||
a->set(v);
|
||||
this->entity = new IfcSelectHelperEntity(t,a);
|
||||
}
|
||||
IfcSelectHelper::IfcSelectHelper(double v, IfcSchema::Type::Enum t) {
|
||||
IfcWriteArgument* a = new IfcWriteArgument(0);
|
||||
a->set(v);
|
||||
this->entity = new IfcSelectHelperEntity(t,a);
|
||||
}
|
||||
IfcSelectHelper::IfcSelectHelper(bool v, IfcSchema::Type::Enum t) {
|
||||
IfcWriteArgument* a = new IfcWriteArgument(0);
|
||||
a->set(v);
|
||||
this->entity = new IfcSelectHelperEntity(t,a);
|
||||
}
|
||||
bool IfcSelectHelper::is(IfcSchema::Type::Enum t) const { return entity->is(t); }
|
||||
IfcSchema::Type::Enum IfcSelectHelper::type() const { return entity->type(); }
|
||||
|
||||
EntityBuffer* EntityBuffer::i = 0;
|
||||
EntityBuffer* EntityBuffer::instance() {
|
||||
if ( ! i ) {
|
||||
|
||||
@@ -119,43 +119,6 @@ namespace IfcWrite {
|
||||
IfcUtil::ArgumentType type() const;
|
||||
};
|
||||
|
||||
/// An entity to help with passing of SELECT arguments that
|
||||
/// consist of simple types, for example useful to initialize
|
||||
/// a new IfcProperty.
|
||||
/// Proper memory management is difficult for now, so beware.
|
||||
class IfcSelectHelperEntity : public IfcAbstractEntity {
|
||||
private:
|
||||
IfcSchema::Type::Enum _type;
|
||||
IfcWriteArgument* arg;
|
||||
public:
|
||||
// FIXME: Make this a non-pointer argument and implement a copy constructor
|
||||
IfcSelectHelperEntity(IfcSchema::Type::Enum t, IfcWriteArgument* a) : _type(t), arg(a) {}
|
||||
IfcEntityList::ptr getInverse(IfcSchema::Type::Enum type, int attribute_index);
|
||||
std::string datatype() const;
|
||||
Argument* getArgument(unsigned int i);
|
||||
unsigned int getArgumentCount() const;
|
||||
IfcSchema::Type::Enum type() const;
|
||||
bool is(IfcSchema::Type::Enum t) const;
|
||||
std::string toString(bool upper = false) const;
|
||||
unsigned int id();
|
||||
IfcWritableEntity* isWritable();
|
||||
};
|
||||
|
||||
/// A helper class for passing of SELECT arguments that
|
||||
/// consist of simple types, for example useful to initialize
|
||||
/// a new IfcProperty.
|
||||
/// Proper memory management is difficult for now, so beware.
|
||||
class IfcSelectHelper : public IfcUtil::IfcBaseClass {
|
||||
public:
|
||||
IfcSelectHelper(const std::string& v, IfcSchema::Type::Enum t=IfcSchema::Type::IfcText);
|
||||
IfcSelectHelper(const char* const v, IfcSchema::Type::Enum t=IfcSchema::Type::IfcText);
|
||||
IfcSelectHelper(int v, IfcSchema::Type::Enum t=IfcSchema::Type::IfcInteger);
|
||||
IfcSelectHelper(double v, IfcSchema::Type::Enum t=IfcSchema::Type::IfcReal);
|
||||
IfcSelectHelper(bool v, IfcSchema::Type::Enum t=IfcSchema::Type::IfcBoolean);
|
||||
bool is(IfcSchema::Type::Enum t) const;
|
||||
IfcSchema::Type::Enum type() const;
|
||||
};
|
||||
|
||||
/// A helper class for the creation of IFC GlobalIds.
|
||||
class IfcGuidHelper {
|
||||
private:
|
||||
|
||||
@@ -39,6 +39,9 @@ namespace IfcUtil {
|
||||
%ignore IfcParse::IfcFile::EntityById;
|
||||
%ignore IfcParse::IfcFile::EntityByGuid;
|
||||
%ignore IfcParse::IfcFile::AddEntity;
|
||||
%ignore IfcParse::IfcFile::removeEntity;
|
||||
%ignore IfcParse::IfcFile::traverse(IfcUtil::IfcBaseClass*, int);
|
||||
%ignore IfcParse::IfcFile::traverse(IfcUtil::IfcBaseClass*);
|
||||
%ignore operator<<;
|
||||
|
||||
%ignore IfcParse::FileDescription::FileDescription;
|
||||
@@ -182,8 +185,14 @@ namespace IfcUtil {
|
||||
IfcParse::IfcLateBoundEntity* by_guid(const std::string& guid) {
|
||||
return (IfcParse::IfcLateBoundEntity*) $self->EntityByGuid(guid);
|
||||
}
|
||||
void add(IfcParse::IfcLateBoundEntity* e) {
|
||||
$self->AddEntity(e);
|
||||
IfcParse::IfcLateBoundEntity* add(IfcParse::IfcLateBoundEntity* e) {
|
||||
return (IfcParse::IfcLateBoundEntity*) $self->AddEntity(e);
|
||||
}
|
||||
void remove(IfcParse::IfcLateBoundEntity* e) {
|
||||
$self->removeEntity(e);
|
||||
}
|
||||
IfcEntityList::ptr traverse(IfcParse::IfcLateBoundEntity* e, int max_level=-1) {
|
||||
return $self->traverse(e, max_level);
|
||||
}
|
||||
void write(const std::string& fn) {
|
||||
std::ofstream f(fn.c_str());
|
||||
|
||||
Reference in New Issue
Block a user