/******************************************************************************** * * * This file is part of IfcOpenShell. * * * * IfcOpenShell is free software: you can redistribute it and/or modify * * it under the terms of the Lesser GNU General Public License as published by * * the Free Software Foundation, either version 3.0 of the License, or * * (at your option) any later version. * * * * IfcOpenShell is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * Lesser GNU General Public License for more details. * * * * You should have received a copy of the Lesser GNU General Public License * * along with this program. If not, see . * * * ********************************************************************************/ // A class declaration to silence SWIG warning about base classes being // undefined, the constructor is private so that SWIG does not wrap them class IfcEntityInstanceData { private: IfcEntityInstanceData(); }; #define invalid_argument(i, arg_name) { throw IfcParse::IfcException(IfcSchema::Type::GetAttributeName(self->entity->type(), (unsigned char)i) + " is not a valid type for '" + arg_name + "'"); } %ignore IfcParse::IfcFile::Init; %ignore IfcParse::IfcFile::entityByGuid; %ignore IfcParse::IfcFile::register_inverse; %ignore IfcParse::IfcFile::unregister_inverse; %ignore operator<<; %ignore IfcParse::FileDescription::FileDescription; %ignore IfcParse::FileName::FileName; %ignore IfcParse::FileSchema::FileSchema; %ignore IfcParse::IfcFile::tokens; %ignore IfcParse::IfcSpfHeader::IfcSpfHeader(IfcSpfLexer*); %ignore IfcParse::IfcSpfHeader::lexer; %ignore IfcParse::IfcSpfHeader::stream; %ignore IfcParse::HeaderEntity::is; %ignore IfcParse::IfcFile::type_iterator; %ignore IfcUtil::IfcBaseClass::is; %rename("by_id") entityById; %rename("by_type") entitiesByType; %rename("__len__") getArgumentCount; %rename("get_argument_type") getArgumentType; %rename("get_argument_name") getArgumentName; %rename("get_argument_index") getArgumentIndex; %rename("get_argument_optionality") getArgumentOptionality; %rename("get_attribute_names") getAttributeNames; %rename("get_inverse_attribute_names") getInverseAttributeNames; %rename("entity_instance") IfcBaseClass; %rename("file") IfcFile; %rename("add") addEntity; %rename("remove") removeEntity; %extend IfcParse::IfcFile { IfcUtil::IfcBaseClass* by_guid(const std::string& guid) { return $self->entityByGuid(guid); } IfcEntityList::ptr get_inverse(IfcUtil::IfcBaseClass* e) { return $self->getInverse(e->entity->id(), IfcSchema::Type::UNDEFINED, -1); } void write(const std::string& fn) { std::ofstream f(fn.c_str()); f << (*$self); } std::vector entity_names() const { std::vector keys; keys.reserve(std::distance($self->begin(), $self->end())); for (IfcParse::IfcFile::entity_by_id_t::const_iterator it = $self->begin(); it != $self->end(); ++ it) { keys.push_back(it->first); } return keys; } std::vector types() const { const size_t n = std::distance($self->types_begin(), $self->types_end()); std::vector ts; ts.reserve(n); std::transform($self->types_begin(), $self->types_end(), std::back_inserter(ts), IfcSchema::Type::ToString); return ts; } std::vector types_with_super() const { const size_t n = std::distance($self->types_incl_super_begin(), $self->types_incl_super_end()); std::vector ts; ts.reserve(n); std::transform($self->types_incl_super_begin(), $self->types_incl_super_end(), std::back_inserter(ts), IfcSchema::Type::ToString); return ts; } %pythoncode %{ # Hide the getters with read-only property implementations header = property(header) %} } %extend IfcUtil::IfcBaseClass { int get_attribute_category(const std::string& name) const { if (IfcSchema::Type::IsSimple($self->type())) { return name == "wrappedValue"; } IfcUtil::IfcBaseEntity* self_ = (IfcUtil::IfcBaseEntity*) self; const std::vector names = self_->getAttributeNames(); if (std::find(names.begin(), names.end(), name) != names.end()) { return 1; } else { const std::vector names = self_->getInverseAttributeNames(); if (std::find(names.begin(), names.end(), name) != names.end()) { return 2; } else { return 0; } } } // id() is defined on IfcBaseEntity and not on IfcBaseClass, in order // to expose it to the Python wrapper it is simply duplicated here. // Same applies to the two methods reimplemented below. int id() const { return $self->entity->id(); } std::vector getAttributeNames() const { if (IfcSchema::Type::IsSimple($self->type())) { return std::vector(1, "wrappedValue"); } IfcUtil::IfcBaseEntity* self_ = (IfcUtil::IfcBaseEntity*) self; return self_->getAttributeNames(); } std::vector getInverseAttributeNames() const { if (IfcSchema::Type::IsSimple($self->type())) { return std::vector(0); } IfcUtil::IfcBaseEntity* self_ = (IfcUtil::IfcBaseEntity*) self; return self_->getInverseAttributeNames(); } bool is_a(const std::string& s) { return self->is(IfcSchema::Type::FromString(boost::to_upper_copy(s))); } std::string is_a() const { return IfcSchema::Type::ToString(self->entity->type()); } std::pair get_argument(unsigned i) { return std::pair($self->getArgumentType(i), $self->getArgument(i)); } std::pair get_argument(const std::string& a) { unsigned i = IfcSchema::Type::GetAttributeIndex($self->type(), a); return std::pair($self->getArgumentType(i), $self->getArgument(i)); } bool __eq__(IfcUtil::IfcBaseClass* other) const { if ($self == other) { return true; } if (IfcSchema::Type::IsSimple($self->type()) || IfcSchema::Type::IsSimple(other->type())) { /// @todo return false; } else { IfcUtil::IfcBaseEntity* self_ = (IfcUtil::IfcBaseEntity*) self; IfcUtil::IfcBaseEntity* other_ = (IfcUtil::IfcBaseEntity*) other; return self_->id() == other_->id() && self_->entity->file == other_->entity->file; } } std::string __repr__() const { return $self->entity->toString(); } // Just something to have a somewhat sensible value to hash size_t file_pointer() const { return reinterpret_cast($self->entity->file); } unsigned get_argument_index(const std::string& a) const { return IfcSchema::Type::GetAttributeIndex(self->entity->type(), a); } IfcEntityList::ptr get_inverse(const std::string& a) { std::pair inv = IfcSchema::Type::GetInverseAttribute(self->entity->type(), a); return self->entity->getInverse(inv.first, inv.second); } void setArgumentAsNull(unsigned int i) { bool is_optional = IfcSchema::Type::GetAttributeOptional(self->entity->type(), (unsigned char)i); if (is_optional) { self->entity->setArgument(i, new IfcWrite::IfcWriteArgument()); } else invalid_argument(i,"NULL"); } void setArgumentAsInt(unsigned int i, int v) { IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(self->entity->type(), (unsigned char)i); if (arg_type == IfcUtil::Argument_INT) { IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument(); arg->set(v); self->entity->setArgument(i, arg); } else if ( (arg_type == IfcUtil::Argument_BOOL) && ( (v == 0) || (v == 1) ) ) { IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument(); arg->set(v == 1); self->entity->setArgument(i, arg); } else invalid_argument(i,"INTEGER"); } void setArgumentAsBool(unsigned int i, bool v) { IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(self->entity->type(), (unsigned char)i); if (arg_type == IfcUtil::Argument_BOOL) { IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument(); arg->set(v); self->entity->setArgument(i, arg); } else invalid_argument(i,"BOOLEAN"); } void setArgumentAsDouble(unsigned int i, double v) { IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(self->entity->type(), (unsigned char)i); if (arg_type == IfcUtil::Argument_DOUBLE) { IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument(); arg->set(v); self->entity->setArgument(i, arg); } else invalid_argument(i,"REAL"); } void setArgumentAsString(unsigned int i, const std::string& a) { IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(self->entity->type(), (unsigned char)i); if (arg_type == IfcUtil::Argument_STRING) { IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument(); arg->set(a); self->entity->setArgument(i, arg); } else if (arg_type == IfcUtil::Argument_ENUMERATION) { std::pair enum_data = IfcSchema::Type::GetEnumerationIndex(IfcSchema::Type::GetAttributeEntity(self->entity->type(), (unsigned char)i), a); IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument(); arg->set(IfcWrite::IfcWriteArgument::EnumerationReference(enum_data.second, enum_data.first)); self->entity->setArgument(i, arg); } else if (arg_type == IfcUtil::Argument_BINARY) { if (IfcUtil::valid_binary_string(a)) { boost::dynamic_bitset<> bits(a); IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument(); arg->set(bits); self->entity->setArgument(i, arg); } else { throw IfcParse::IfcException("String not a valid binary representation"); } } else invalid_argument(i,"STRING"); } void setArgumentAsAggregateOfInt(unsigned int i, const std::vector& v) { IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(self->entity->type(), (unsigned char)i); if (arg_type == IfcUtil::Argument_AGGREGATE_OF_INT) { IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument(); arg->set(v); self->entity->setArgument(i, arg); } else invalid_argument(i,"AGGREGATE OF INT"); } void setArgumentAsAggregateOfDouble(unsigned int i, const std::vector& v) { IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(self->entity->type(), (unsigned char)i); if (arg_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) { IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument(); arg->set(v); self->entity->setArgument(i, arg); } else invalid_argument(i,"AGGREGATE OF DOUBLE"); } void setArgumentAsAggregateOfString(unsigned int i, const std::vector& v) { IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(self->entity->type(), (unsigned char)i); if (arg_type == IfcUtil::Argument_AGGREGATE_OF_STRING) { IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument(); arg->set(v); self->entity->setArgument(i, arg); } else if (arg_type == IfcUtil::Argument_AGGREGATE_OF_BINARY) { std::vector< boost::dynamic_bitset<> > bits; bits.reserve(v.size()); for (std::vector::const_iterator it = v.begin(); it != v.end(); ++it) { if (IfcUtil::valid_binary_string(*it)) { bits.push_back(boost::dynamic_bitset<>(*it)); } else { throw IfcParse::IfcException("String not a valid binary representation"); } } IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument(); arg->set(bits); self->entity->setArgument(i, arg); } else invalid_argument(i,"AGGREGATE OF STRING"); } void setArgumentAsEntityInstance(unsigned int i, IfcUtil::IfcBaseClass* v) { IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(self->entity->type(), (unsigned char)i); if (arg_type == IfcUtil::Argument_ENTITY_INSTANCE) { IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument(); arg->set(v); self->entity->setArgument(i, arg); } else invalid_argument(i,"ENTITY INSTANCE"); } void setArgumentAsAggregateOfEntityInstance(unsigned int i, IfcEntityList::ptr v) { IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(self->entity->type(), (unsigned char)i); if (arg_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) { IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument(); arg->set(v); self->entity->setArgument(i, arg); } else invalid_argument(i,"AGGREGATE OF ENTITY INSTANCE"); } void setArgumentAsAggregateOfAggregateOfInt(unsigned int i, const std::vector< std::vector >& v) { IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(self->entity->type(), (unsigned char)i); if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT) { IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument(); arg->set(v); self->entity->setArgument(i, arg); } else invalid_argument(i,"AGGREGATE OF AGGREGATE OF INT"); } void setArgumentAsAggregateOfAggregateOfDouble(unsigned int i, const std::vector< std::vector >& v) { IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(self->entity->type(), (unsigned char)i); if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE) { IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument(); arg->set(v); self->entity->setArgument(i, arg); } else invalid_argument(i,"AGGREGATE OF AGGREGATE OF DOUBLE"); } void setArgumentAsAggregateOfAggregateOfEntityInstance(unsigned int i, IfcEntityListList::ptr v) { IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(self->entity->type(), (unsigned char)i); if (arg_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) { IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument(); arg->set(v); self->entity->setArgument(i, arg); } else invalid_argument(i,"AGGREGATE OF AGGREGATE OF ENTITY INSTANCE"); } } %extend IfcParse::IfcSpfHeader { %pythoncode %{ # Hide the getters with read-only property implementations file_description = property(file_description) file_name = property(file_name) file_schema = property(file_schema) %} }; %extend IfcParse::FileDescription { %pythoncode %{ # Hide the getters with read-write property implementations __swig_getmethods__["description"] = description __swig_setmethods__["description"] = description description = property(description, description) __swig_getmethods__["implementation_level"] = implementation_level __swig_setmethods__["implementation_level"] = implementation_level implementation_level = property(implementation_level, implementation_level) %} }; %extend IfcParse::FileName { %pythoncode %{ # Hide the getters with read-write property implementations __swig_getmethods__["name"] = name __swig_setmethods__["name"] = name name = property(name, name) __swig_getmethods__["time_stamp"] = time_stamp __swig_setmethods__["time_stamp"] = time_stamp time_stamp = property(time_stamp, time_stamp) __swig_getmethods__["author"] = author __swig_setmethods__["author"] = author author = property(author, author) __swig_getmethods__["organization"] = organization __swig_setmethods__["organization"] = organization organization = property(organization, organization) __swig_getmethods__["preprocessor_version"] = preprocessor_version __swig_setmethods__["preprocessor_version"] = preprocessor_version preprocessor_version = property(preprocessor_version, preprocessor_version) __swig_getmethods__["originating_system"] = originating_system __swig_setmethods__["originating_system"] = originating_system originating_system = property(originating_system, originating_system) __swig_getmethods__["authorization"] = authorization __swig_setmethods__["authorization"] = authorization authorization = property(authorization, authorization) %} }; %extend IfcParse::FileSchema { %pythoncode %{ # Hide the getters with read-write property implementations __swig_getmethods__["schema_identifiers"] = schema_identifiers __swig_setmethods__["schema_identifiers"] = schema_identifiers schema_identifiers = property(schema_identifiers, schema_identifiers) %} }; %include "../ifcparse/ifc_parse_api.h" %include "../ifcparse/IfcSpfHeader.h" %include "../ifcparse/IfcFile.h" %include "../ifcparse/IfcBaseClass.h" // The IfcFile* returned by open() is to be freed by SWIG/Python %newobject open; %newobject read; %inline %{ IfcParse::IfcFile* open(const std::string& fn) { IfcParse::IfcFile* f = new IfcParse::IfcFile(); f->Init(fn); return f; } IfcParse::IfcFile* read(const std::string& data) { char* copiedData = new char[data.length()]; memcpy(copiedData, data.c_str(), data.length()); IfcParse::IfcFile* f = new IfcParse::IfcFile(); f->Init((void *)copiedData, data.length()); return f; } const char* schema_identifier() { return IfcSchema::Identifier; } const char* version() { return IFCOPENSHELL_VERSION; } std::string get_supertype(std::string n) { boost::to_upper(n); IfcSchema::Type::Enum t = IfcSchema::Type::FromString(n); if (IfcSchema::Type::Parent(t)) { return IfcSchema::Type::ToString(*IfcSchema::Type::Parent(t)); } else { return ""; } } IfcUtil::IfcBaseClass* new_IfcBaseClass(const std::string& s) { IfcSchema::Type::Enum ty = IfcSchema::Type::FromString(boost::to_upper_copy(s)); IfcEntityInstanceData* data = new IfcEntityInstanceData(ty); data->setArgument(IfcSchema::Type::GetAttributeCount(ty) - 1, new IfcWrite::IfcWriteArgument()); IfcSchema::Type::PopulateDerivedFields(data); return IfcSchema::SchemaEntity(data); } %} %{ static std::stringstream ifcopenshell_log_stream; %} %init %{ Logger::SetOutput(0, &ifcopenshell_log_stream); %} %inline %{ std::string get_log() { std::string log = ifcopenshell_log_stream.str(); ifcopenshell_log_stream.str(""); return log; } %}