mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-14 19:34:34 +00:00
ifcparse refactoring (#190)
Unify attribute containers, provide latebound attribute access on IfcBaseEntity, more basic tests on Travis
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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 <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef ARGUMENT_H
|
||||
#define ARGUMENT_H
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "ifc_parse_api.h"
|
||||
|
||||
#ifdef USE_IFC4
|
||||
#include "../ifcparse/Ifc4enum.h"
|
||||
#else
|
||||
#include "../ifcparse/Ifc2x3enum.h"
|
||||
#endif
|
||||
|
||||
#include "../ifcparse/IfcEntityList.h"
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/dynamic_bitset.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#define foreach BOOST_FOREACH
|
||||
#define rforeach BOOST_REVERSE_FOREACH
|
||||
|
||||
class Argument;
|
||||
class IfcEntityList;
|
||||
class IfcEntityListList;
|
||||
class IfcEntityInstanceData;
|
||||
namespace IfcParse {
|
||||
class IfcFile;
|
||||
}
|
||||
namespace IfcUtil {
|
||||
class IfcBaseClass;
|
||||
|
||||
IFC_PARSE_API const char* ArgumentTypeToString(ArgumentType argument_type);
|
||||
|
||||
IFC_PARSE_API bool valid_binary_string(const std::string& s);
|
||||
/// Replaces spaces and potentially other problem causing characters with underscores.
|
||||
IFC_PARSE_API void sanitate_material_name(std::string &str);
|
||||
IFC_PARSE_API void escape_xml(std::string &str);
|
||||
IFC_PARSE_API void unescape_xml(std::string &str);
|
||||
}
|
||||
|
||||
class IFC_PARSE_API Argument {
|
||||
public:
|
||||
virtual operator int() const;
|
||||
virtual operator bool() const;
|
||||
virtual operator double() const;
|
||||
virtual operator std::string() const;
|
||||
virtual operator boost::dynamic_bitset<>() const;
|
||||
virtual operator IfcUtil::IfcBaseClass*() const;
|
||||
|
||||
virtual operator std::vector<int>() const;
|
||||
virtual operator std::vector<double>() const;
|
||||
virtual operator std::vector<std::string>() const;
|
||||
virtual operator std::vector<boost::dynamic_bitset<> >() const;
|
||||
virtual operator IfcEntityList::ptr() const;
|
||||
|
||||
virtual operator std::vector< std::vector<int> >() const;
|
||||
virtual operator std::vector< std::vector<double> >() const;
|
||||
virtual operator IfcEntityListList::ptr() const;
|
||||
|
||||
virtual bool isNull() const = 0;
|
||||
virtual unsigned int size() const = 0;
|
||||
|
||||
virtual IfcUtil::ArgumentType type() const = 0;
|
||||
virtual Argument* operator [] (unsigned int i) const = 0;
|
||||
virtual std::string toString(bool upper=false) const = 0;
|
||||
|
||||
virtual ~Argument() {};
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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 <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef ARGUMENTTYPE_H
|
||||
#define ARGUMENTTYPE_H
|
||||
|
||||
namespace IfcUtil {
|
||||
|
||||
enum ArgumentType {
|
||||
Argument_NULL,
|
||||
Argument_DERIVED,
|
||||
Argument_INT,
|
||||
Argument_BOOL,
|
||||
Argument_DOUBLE,
|
||||
Argument_STRING,
|
||||
Argument_BINARY,
|
||||
Argument_ENUMERATION,
|
||||
Argument_ENTITY_INSTANCE,
|
||||
|
||||
Argument_EMPTY_AGGREGATE,
|
||||
Argument_AGGREGATE_OF_INT,
|
||||
Argument_AGGREGATE_OF_DOUBLE,
|
||||
Argument_AGGREGATE_OF_STRING,
|
||||
Argument_AGGREGATE_OF_BINARY,
|
||||
Argument_AGGREGATE_OF_ENTITY_INSTANCE,
|
||||
|
||||
Argument_AGGREGATE_OF_EMPTY_AGGREGATE,
|
||||
Argument_AGGREGATE_OF_AGGREGATE_OF_INT,
|
||||
Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE,
|
||||
Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE,
|
||||
|
||||
Argument_UNKNOWN
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -17,14 +17,12 @@
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************************
|
||||
* *
|
||||
* This file has been generated from *
|
||||
* http://www.buildingsmart-tech.org/downloads/ifc/ifc2x3tc/IFC2X3_TC1_EXPRESS_longform.zip *
|
||||
* Do not make modifications but instead modify the Python script that has been *
|
||||
* used to generate this. *
|
||||
* *
|
||||
********************************************************************************************/
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file has been generated from IFC2X3_TC1.exp. Do not make modifications *
|
||||
* but instead modify the python script that has been used to generate this. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef USE_IFC4
|
||||
|
||||
@@ -34,8 +32,7 @@
|
||||
#include "../ifcparse/Ifc2x3-latebound.h"
|
||||
#include "../ifcparse/IfcException.h"
|
||||
#include "../ifcparse/IfcWrite.h"
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcBaseClass.h"
|
||||
#include "../ifcparse/IfcEntityDescriptor.h"
|
||||
|
||||
using namespace Ifc2x3;
|
||||
@@ -4296,12 +4293,14 @@ std::set<std::string> Type::GetInverseAttributeNames(Enum t) {
|
||||
return return_value;
|
||||
}
|
||||
|
||||
void Type::PopulateDerivedFields(IfcWrite::IfcWritableEntity* e) {
|
||||
void Type::PopulateDerivedFields(IfcEntityInstanceData* e) {
|
||||
if (derived_map.empty()) ::InitDerivedMap();
|
||||
std::map<Type::Enum, std::set<int> >::const_iterator i = derived_map.find(e->type());
|
||||
if (i != derived_map.end()) {
|
||||
for (std::set<int>::const_iterator it = i->second.begin(); it != i->second.end(); ++it) {
|
||||
e->setArgumentDerived(*it);
|
||||
IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();
|
||||
attr->set(IfcWrite::IfcWriteArgument::Derived());
|
||||
e->setArgument(*it, attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,14 +17,12 @@
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************************
|
||||
* *
|
||||
* This file has been generated from *
|
||||
* http://www.buildingsmart-tech.org/downloads/ifc/ifc2x3tc/IFC2X3_TC1_EXPRESS_longform.zip *
|
||||
* Do not make modifications but instead modify the Python script that has been *
|
||||
* used to generate this. *
|
||||
* *
|
||||
********************************************************************************************/
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file has been generated from IFC2X3_TC1.exp. Do not make modifications *
|
||||
* but instead modify the python script that has been used to generate this. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFC2X3RT_H
|
||||
#define IFC2X3RT_H
|
||||
@@ -32,9 +30,8 @@
|
||||
#define IfcSchema Ifc2x3
|
||||
|
||||
#include "../ifcparse/ifc_parse_api.h"
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcBaseClass.h"
|
||||
#include "../ifcparse/IfcEntityDescriptor.h"
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
|
||||
namespace Ifc2x3 {
|
||||
namespace Type {
|
||||
@@ -48,7 +45,7 @@ namespace Type {
|
||||
IFC_PARSE_API std::pair<const char*, int> GetEnumerationIndex(Enum t, const std::string& a);
|
||||
IFC_PARSE_API std::pair<Enum, unsigned> GetInverseAttribute(Enum t, const std::string& a);
|
||||
IFC_PARSE_API std::set<std::string> GetInverseAttributeNames(Enum t);
|
||||
IFC_PARSE_API void PopulateDerivedFields(IfcWrite::IfcWritableEntity* e);
|
||||
IFC_PARSE_API void PopulateDerivedFields(IfcEntityInstanceData* e);
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
+2867
-2870
File diff suppressed because one or more lines are too long
+781
-780
File diff suppressed because it is too large
Load Diff
@@ -17,20 +17,19 @@
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************************
|
||||
* *
|
||||
* This file has been generated from *
|
||||
* http://www.buildingsmart-tech.org/downloads/ifc/ifc2x3tc/IFC2X3_TC1_EXPRESS_longform.zip *
|
||||
* Do not make modifications but instead modify the Python script that has been *
|
||||
* used to generate this. *
|
||||
* *
|
||||
********************************************************************************************/
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file has been generated from IFC2X3_TC1.exp. Do not make modifications *
|
||||
* but instead modify the python script that has been used to generate this. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFC2X3ENUM_H
|
||||
#define IFC2X3ENUM_H
|
||||
|
||||
#include "../ifcparse/ifc_parse_api.h"
|
||||
|
||||
#include <string>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#define IfcSchema Ifc2x3
|
||||
|
||||
@@ -19,10 +19,8 @@
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file has been generated from *
|
||||
* http://www.buildingsmart-tech.org/ifc/IFC4/Add1/IFC4_ADD1.exp *
|
||||
* Do not make modifications but instead modify the Python script that has been *
|
||||
* used to generate this. *
|
||||
* This file has been generated from IFC4.exp. Do not make modifications *
|
||||
* but instead modify the python script that has been used to generate this. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
@@ -34,8 +32,7 @@
|
||||
#include "../ifcparse/Ifc4-latebound.h"
|
||||
#include "../ifcparse/IfcException.h"
|
||||
#include "../ifcparse/IfcWrite.h"
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcBaseClass.h"
|
||||
#include "../ifcparse/IfcEntityDescriptor.h"
|
||||
|
||||
using namespace Ifc4;
|
||||
@@ -5013,12 +5010,14 @@ std::set<std::string> Type::GetInverseAttributeNames(Enum t) {
|
||||
return return_value;
|
||||
}
|
||||
|
||||
void Type::PopulateDerivedFields(IfcWrite::IfcWritableEntity* e) {
|
||||
void Type::PopulateDerivedFields(IfcEntityInstanceData* e) {
|
||||
if (derived_map.empty()) ::InitDerivedMap();
|
||||
std::map<Type::Enum, std::set<int> >::const_iterator i = derived_map.find(e->type());
|
||||
if (i != derived_map.end()) {
|
||||
for (std::set<int>::const_iterator it = i->second.begin(); it != i->second.end(); ++it) {
|
||||
e->setArgumentDerived(*it);
|
||||
IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();
|
||||
attr->set(IfcWrite::IfcWriteArgument::Derived());
|
||||
e->setArgument(*it, attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,10 +19,8 @@
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file has been generated from *
|
||||
* http://www.buildingsmart-tech.org/ifc/IFC4/Add1/IFC4_ADD1.exp *
|
||||
* Do not make modifications but instead modify the Python script that has been *
|
||||
* used to generate this. *
|
||||
* This file has been generated from IFC4.exp. Do not make modifications *
|
||||
* but instead modify the python script that has been used to generate this. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
@@ -32,9 +30,8 @@
|
||||
#define IfcSchema Ifc4
|
||||
|
||||
#include "../ifcparse/ifc_parse_api.h"
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcBaseClass.h"
|
||||
#include "../ifcparse/IfcEntityDescriptor.h"
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
|
||||
namespace Ifc4 {
|
||||
namespace Type {
|
||||
@@ -48,7 +45,7 @@ namespace Type {
|
||||
IFC_PARSE_API std::pair<const char*, int> GetEnumerationIndex(Enum t, const std::string& a);
|
||||
IFC_PARSE_API std::pair<Enum, unsigned> GetInverseAttribute(Enum t, const std::string& a);
|
||||
IFC_PARSE_API std::set<std::string> GetInverseAttributeNames(Enum t);
|
||||
IFC_PARSE_API void PopulateDerivedFields(IfcWrite::IfcWritableEntity* e);
|
||||
IFC_PARSE_API void PopulateDerivedFields(IfcEntityInstanceData* e);
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
+3281
-3284
File diff suppressed because one or more lines are too long
+906
-905
File diff suppressed because it is too large
Load Diff
@@ -19,10 +19,8 @@
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file has been generated from *
|
||||
* http://www.buildingsmart-tech.org/ifc/IFC4/Add1/IFC4_ADD1.exp *
|
||||
* Do not make modifications but instead modify the Python script that has been *
|
||||
* used to generate this. *
|
||||
* This file has been generated from IFC4.exp. Do not make modifications *
|
||||
* but instead modify the python script that has been used to generate this. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
@@ -31,6 +29,7 @@
|
||||
|
||||
#include "../ifcparse/ifc_parse_api.h"
|
||||
|
||||
#include <string>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#define IfcSchema Ifc4
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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 <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCBASECLASS_H
|
||||
#define IFCBASECLASS_H
|
||||
|
||||
#include "ifc_parse_api.h"
|
||||
|
||||
#ifdef USE_IFC4
|
||||
#include "../ifcparse/Ifc4enum.h"
|
||||
#else
|
||||
#include "../ifcparse/Ifc2x3enum.h"
|
||||
#endif
|
||||
|
||||
#include "../ifcparse/IfcEntityInstanceData.h"
|
||||
|
||||
class Argument;
|
||||
|
||||
namespace IfcUtil {
|
||||
|
||||
class IFC_PARSE_API IfcBaseClass {
|
||||
public:
|
||||
virtual ~IfcBaseClass() {}
|
||||
IfcEntityInstanceData* entity;
|
||||
virtual bool is(IfcSchema::Type::Enum v) const = 0;
|
||||
virtual IfcSchema::Type::Enum type() const = 0;
|
||||
|
||||
virtual unsigned int getArgumentCount() const = 0;
|
||||
virtual IfcUtil::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;
|
||||
|
||||
template <class T>
|
||||
T* as() {
|
||||
return is(T::Class())
|
||||
? static_cast<T*>(this)
|
||||
: static_cast<T*>(0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const T* as() const {
|
||||
return is(T::Class())
|
||||
? static_cast<const T*>(this)
|
||||
: static_cast<const T*>(0);
|
||||
}
|
||||
};
|
||||
|
||||
class IFC_PARSE_API IfcBaseEntity : public IfcBaseClass {
|
||||
public:
|
||||
Argument* getArgumentByName(const std::string& name) const;
|
||||
std::vector<std::string> getAttributeNames() const;
|
||||
std::vector<std::string> getInverseAttributeNames() const;
|
||||
unsigned id() const { return entity->id(); }
|
||||
};
|
||||
|
||||
// TODO: Investigate whether these should be template classes instead
|
||||
class IFC_PARSE_API IfcBaseType : public IfcBaseEntity {
|
||||
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; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcBaseClass.h"
|
||||
#include "../ifcparse/IfcException.h"
|
||||
|
||||
#ifdef USE_IFC4
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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 <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCENTITYINSTANCEDATA_H
|
||||
#define IFCENTITYINSTANCEDATA_H
|
||||
|
||||
#include "../ifcparse/ArgumentType.h"
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
class Argument;
|
||||
class IfcEntityList;
|
||||
namespace IfcParse {
|
||||
class IfcFile;
|
||||
}
|
||||
|
||||
class IFC_PARSE_API IfcEntityInstanceData {
|
||||
public:
|
||||
// Public for backwards compatibility
|
||||
IfcParse::IfcFile* file;
|
||||
protected:
|
||||
unsigned id_;
|
||||
IfcSchema::Type::Enum type_;
|
||||
mutable std::vector<Argument*> attributes_;
|
||||
|
||||
// To reduce memory footprint, these two could potentially be combined,
|
||||
// e.g. initialized_ <-> offset_in_file_ == 0, but it would imply that
|
||||
// instances cannot be located at the beginning of the file. Officially
|
||||
// there should be a header anyways.
|
||||
mutable bool initialized_;
|
||||
unsigned offset_in_file_;
|
||||
|
||||
void load_() const;
|
||||
public:
|
||||
IfcEntityInstanceData(IfcSchema::Type::Enum type, IfcParse::IfcFile* file_, unsigned id = 0, unsigned offset_in_file = 0)
|
||||
: file(file_), id_(id), type_(type), initialized_(false), offset_in_file_(offset_in_file)
|
||||
{}
|
||||
|
||||
IfcEntityInstanceData(IfcSchema::Type::Enum type)
|
||||
: file(0), id_(0), type_(type), initialized_(true)
|
||||
{}
|
||||
|
||||
/*
|
||||
IfcEntityInstanceData(IfcParse::IfcFile* file = 0, unsigned id = 0, IfcSchema::Type::Enum type = IfcSchema::Type::UNDEFINED, unsigned offset_in_file = 0, size_t n)
|
||||
: file_(file), id_(0), type_(type), initialized_(false)
|
||||
{
|
||||
attributes_.reserve(n);
|
||||
}
|
||||
|
||||
IfcEntityInstanceData(IfcParse::IfcFile* file = 0, unsigned id = 0, IfcSchema::Type::Enum type = IfcSchema::Type::UNDEFINED, const std::vector<Argument*>& attributes)
|
||||
: file_(file), id_(0), type_(type), attributes_(attributes), initialized_(true)
|
||||
{}
|
||||
*/
|
||||
|
||||
IfcEntityInstanceData(const IfcEntityInstanceData& e);
|
||||
|
||||
~IfcEntityInstanceData();
|
||||
|
||||
boost::shared_ptr<IfcEntityList> getInverse(IfcSchema::Type::Enum type, int attribute_index);
|
||||
|
||||
Argument* getArgument(unsigned int i) const;
|
||||
|
||||
// NB: This makes a copy of the argument
|
||||
void setArgument(unsigned int i, Argument* a, IfcUtil::ArgumentType attr_type = IfcUtil::Argument_UNKNOWN);
|
||||
|
||||
unsigned int getArgumentCount() const {
|
||||
if (!initialized_) {
|
||||
load_();
|
||||
}
|
||||
return attributes_.size();
|
||||
}
|
||||
|
||||
IfcSchema::Type::Enum type() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
std::string toString(bool upper = false) const;
|
||||
|
||||
unsigned int id() const { return id_; }
|
||||
unsigned int offset_in_file() const { return offset_in_file_; }
|
||||
|
||||
// NB: const ommitted for lazy loading
|
||||
std::vector<Argument*>& attributes() const { return attributes_; }
|
||||
|
||||
unsigned set_id(boost::optional<unsigned> i = boost::none);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,184 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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 <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCENTITYLIST_H
|
||||
#define IFCENTITYLIST_H
|
||||
|
||||
#include "../ifcparse/IfcBaseClass.h"
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <set>
|
||||
|
||||
template <class T>
|
||||
class IfcTemplatedEntityList;
|
||||
|
||||
class IFC_PARSE_API IfcEntityList {
|
||||
std::vector<IfcUtil::IfcBaseClass*> ls;
|
||||
public:
|
||||
typedef boost::shared_ptr<IfcEntityList> ptr;
|
||||
typedef std::vector<IfcUtil::IfcBaseClass*>::const_iterator it;
|
||||
void push(IfcUtil::IfcBaseClass* l);
|
||||
void push(const ptr& l);
|
||||
it begin();
|
||||
it end();
|
||||
IfcUtil::IfcBaseClass* operator[] (int i);
|
||||
unsigned int size() const;
|
||||
bool contains(IfcUtil::IfcBaseClass*) const;
|
||||
template <class U>
|
||||
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);
|
||||
return r;
|
||||
}
|
||||
void remove(IfcUtil::IfcBaseClass*);
|
||||
IfcEntityList::ptr filtered(const std::set<IfcSchema::Type::Enum>& entities);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class IfcTemplatedEntityList {
|
||||
std::vector<T*> ls;
|
||||
public:
|
||||
typedef boost::shared_ptr< IfcTemplatedEntityList<T> > ptr;
|
||||
typedef typename std::vector<T*>::const_iterator it;
|
||||
void push(T* t) { if (t) { ls.push_back(t); } }
|
||||
void push(ptr t) { if (t) { for (typename T::list::it it = t->begin(); it != t->end(); ++it) push(*it); } }
|
||||
it begin() { return ls.begin(); }
|
||||
it end() { return ls.end(); }
|
||||
unsigned int size() const { return (unsigned int)ls.size(); }
|
||||
IfcEntityList::ptr generalize() {
|
||||
IfcEntityList::ptr r(new IfcEntityList());
|
||||
for (it i = begin(); i != end(); ++i) r->push(*i);
|
||||
return r;
|
||||
}
|
||||
bool contains(T* t) const { return std::find(ls.begin(), ls.end(), t) != ls.end(); }
|
||||
template <class U>
|
||||
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);
|
||||
return r;
|
||||
}
|
||||
void remove(T* t) {
|
||||
typename std::vector<T*>::iterator it;
|
||||
while ((it = std::find(ls.begin(), ls.end(), t)) != ls.end()) {
|
||||
ls.erase(it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class IfcTemplatedEntityListList;
|
||||
|
||||
class IFC_PARSE_API IfcEntityListList {
|
||||
std::vector< std::vector<IfcUtil::IfcBaseClass*> > ls;
|
||||
public:
|
||||
typedef boost::shared_ptr< IfcEntityListList > ptr;
|
||||
typedef std::vector< std::vector<IfcUtil::IfcBaseClass*> >::const_iterator outer_it;
|
||||
typedef std::vector<IfcUtil::IfcBaseClass*>::const_iterator inner_it;
|
||||
void push(const std::vector<IfcUtil::IfcBaseClass*>& l) {
|
||||
ls.push_back(l);
|
||||
}
|
||||
void push(const IfcEntityList::ptr& l) {
|
||||
if (l) {
|
||||
std::vector<IfcUtil::IfcBaseClass*> li;
|
||||
for (std::vector<IfcUtil::IfcBaseClass*>::const_iterator jt = l->begin(); jt != l->end(); ++jt) {
|
||||
li.push_back(*jt);
|
||||
}
|
||||
push(li);
|
||||
}
|
||||
}
|
||||
outer_it begin() const { return ls.begin(); }
|
||||
outer_it end() const { return ls.end(); }
|
||||
int size() const { return (int)ls.size(); }
|
||||
int totalSize() const {
|
||||
int accum = 0;
|
||||
for (outer_it it = begin(); it != end(); ++it) {
|
||||
accum += (int)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;
|
||||
if (std::find(inner.begin(), inner.end(), instance) != inner.end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template <class U>
|
||||
typename IfcTemplatedEntityListList<U>::ptr as() {
|
||||
typename IfcTemplatedEntityListList<U>::ptr r(new IfcTemplatedEntityListList<U>);
|
||||
const bool all = U::Class() == IfcSchema::Type::UNDEFINED;
|
||||
for (outer_it outer = begin(); outer != end(); ++outer) {
|
||||
const std::vector<IfcUtil::IfcBaseClass*>& from = *outer;
|
||||
typename std::vector<U*> to;
|
||||
for (inner_it inner = from.begin(); inner != from.end(); ++inner) {
|
||||
if (all || (*inner)->is(U::Class())) to.push_back((U*)*inner);
|
||||
}
|
||||
r->push(to);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class IfcTemplatedEntityListList {
|
||||
std::vector< std::vector<T*> > ls;
|
||||
public:
|
||||
typedef typename boost::shared_ptr< IfcTemplatedEntityListList<T> > ptr;
|
||||
typedef typename std::vector< std::vector<T*> >::const_iterator outer_it;
|
||||
typedef typename std::vector<T*>::const_iterator inner_it;
|
||||
void push(const std::vector<T*>& t) { ls.push_back(t); }
|
||||
outer_it begin() { return ls.begin(); }
|
||||
outer_it end() { return ls.end(); }
|
||||
int size() const { return (int)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;
|
||||
if (std::find(inner.begin(), inner.end(), t) != inner.end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
IfcEntityListList::ptr generalize() {
|
||||
IfcEntityListList::ptr r(new IfcEntityListList());
|
||||
for (outer_it outer = begin(); outer != end(); ++outer) {
|
||||
const std::vector<T*>& from = *outer;
|
||||
std::vector<IfcUtil::IfcBaseClass*> to;
|
||||
for (inner_it inner = from.begin(); inner != from.end(); ++inner) {
|
||||
to.push_back(*inner);
|
||||
}
|
||||
r->push(to);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -37,34 +37,31 @@ public:
|
||||
typedef std::map<IfcSchema::Type::Enum, IfcEntityList::ptr> entities_by_type_t;
|
||||
typedef std::map<unsigned int, IfcUtil::IfcBaseClass*> entity_by_id_t;
|
||||
typedef std::map<std::string, IfcSchema::IfcRoot*> entity_by_guid_t;
|
||||
typedef std::map<unsigned int, IfcEntityList::ptr> entities_by_ref_t;
|
||||
typedef std::map<unsigned int, unsigned int> offset_by_id_t;
|
||||
typedef std::map<unsigned int, std::vector<unsigned int> > entities_by_ref_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;
|
||||
bool parsing_complete_;
|
||||
|
||||
entity_by_id_t byid;
|
||||
entities_by_type_t bytype;
|
||||
entities_by_ref_t byref;
|
||||
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);
|
||||
void register_inverse(unsigned, Token);
|
||||
public:
|
||||
IfcParse::IfcSpfLexer* tokens;
|
||||
IfcParse::IfcSpfStream* stream;
|
||||
|
||||
IfcFile(bool create_latebound_entities = false);
|
||||
IfcFile();
|
||||
~IfcFile();
|
||||
|
||||
/// Returns the first entity in the file, this probably is the entity
|
||||
@@ -130,9 +127,10 @@ public:
|
||||
|
||||
std::string createTimestamp() const;
|
||||
|
||||
bool create_latebound_entities() const { return _create_latebound_entities; }
|
||||
|
||||
std::pair<IfcSchema::IfcNamedUnit*, double> getUnit(IfcSchema::IfcUnitEnum::IfcUnitEnum);
|
||||
|
||||
void load(const IfcEntityInstanceData&);
|
||||
void load(unsigned entity_instance_name, std::vector<Argument*>& attributes);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include "../ifcparse/IfcGlobalId.h"
|
||||
#include "../ifcparse/IfcException.h"
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcBaseClass.h"
|
||||
#include "../ifcparse/IfcLogger.h"
|
||||
|
||||
static const char* chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_$";
|
||||
|
||||
@@ -1,261 +0,0 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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 <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcWrite.h"
|
||||
|
||||
#ifdef USE_IFC4
|
||||
#include "../ifcparse/Ifc4-latebound.h"
|
||||
#else
|
||||
#include "../ifcparse/Ifc2x3-latebound.h"
|
||||
#endif
|
||||
|
||||
#include "IfcLateBoundEntity.h"
|
||||
|
||||
using namespace IfcUtil;
|
||||
|
||||
IfcWrite::IfcWritableEntity* IfcParse::IfcLateBoundEntity::writable_entity() {
|
||||
IfcWrite::IfcWritableEntity* e;
|
||||
if (entity->isWritable()) {
|
||||
e = (IfcWrite::IfcWritableEntity*) entity;
|
||||
} else {
|
||||
entity = e = new IfcWrite::IfcWritableEntity(entity);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
IfcParse::IfcLateBoundEntity::IfcLateBoundEntity(const std::string& s) {
|
||||
IfcSchema::Type::Enum ty = IfcSchema::Type::FromString(boost::to_upper_copy(s));
|
||||
entity = new IfcWrite::IfcWritableEntity(ty);
|
||||
for (unsigned i = 0; i < getArgumentCount(); ++i) {
|
||||
// Side effect of this is that a NULL attribute is created.
|
||||
entity->getArgument(i);
|
||||
}
|
||||
IfcSchema::Type::PopulateDerivedFields(writable_entity());
|
||||
}
|
||||
IfcParse::IfcLateBoundEntity::IfcLateBoundEntity(IfcAbstractEntity* e) {
|
||||
entity = e;
|
||||
}
|
||||
unsigned int IfcParse::IfcLateBoundEntity::id() const {
|
||||
if (entity->file) {
|
||||
return static_cast<unsigned int>(entity->id());
|
||||
} else {
|
||||
throw IfcException("Entity not bound to a file");
|
||||
}
|
||||
}
|
||||
bool IfcParse::IfcLateBoundEntity::is(IfcSchema::Type::Enum v) const {
|
||||
IfcSchema::Type::Enum _ty = entity->type();
|
||||
if (v == _ty) return true;
|
||||
while (IfcSchema::Type::Parent(_ty)) {
|
||||
_ty = *IfcSchema::Type::Parent(_ty);
|
||||
if (v == _ty) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
std::string IfcParse::IfcLateBoundEntity::is_a() const {
|
||||
return IfcSchema::Type::ToString(entity->type());
|
||||
}
|
||||
bool IfcParse::IfcLateBoundEntity::is_a(const std::string& s) const {
|
||||
return is(IfcSchema::Type::FromString(boost::to_upper_copy(s)));
|
||||
}
|
||||
IfcSchema::Type::Enum IfcParse::IfcLateBoundEntity::type() const {
|
||||
return entity->type();
|
||||
}
|
||||
unsigned int IfcParse::IfcLateBoundEntity::getArgumentCount() const {
|
||||
return IfcSchema::Type::GetAttributeCount(entity->type());
|
||||
}
|
||||
IfcUtil::ArgumentType IfcParse::IfcLateBoundEntity::getArgumentType(unsigned int i) const {
|
||||
return IfcSchema::Type::GetAttributeDerived(entity->type(), (unsigned char)i)
|
||||
? IfcUtil::Argument_DERIVED
|
||||
: IfcSchema::Type::GetAttributeType(entity->type(), (unsigned char)i);
|
||||
}
|
||||
IfcSchema::Type::Enum IfcParse::IfcLateBoundEntity::getArgumentEntity(unsigned int i) const {
|
||||
return IfcSchema::Type::GetAttributeEntity(entity->type(), (unsigned char)i);
|
||||
}
|
||||
Argument* IfcParse::IfcLateBoundEntity::getArgument(unsigned int i) const {
|
||||
return entity->getArgument(i);
|
||||
}
|
||||
const char* IfcParse::IfcLateBoundEntity::getArgumentName(unsigned int i) const {
|
||||
return IfcSchema::Type::GetAttributeName(entity->type(), (unsigned char)i).c_str();
|
||||
}
|
||||
bool IfcParse::IfcLateBoundEntity::getArgumentOptionality(unsigned int i) const {
|
||||
return IfcSchema::Type::GetAttributeOptional(entity->type(), (unsigned char)i);
|
||||
}
|
||||
|
||||
void IfcParse::IfcLateBoundEntity::invalid_argument(unsigned int i, const std::string& t) {
|
||||
const std::string arg_name = IfcSchema::Type::GetAttributeName(entity->type(), (unsigned char)i);
|
||||
throw IfcException(t + " is not a valid type for '" + arg_name + "'");
|
||||
}
|
||||
void IfcParse::IfcLateBoundEntity::setArgumentAsNull(unsigned int i) {
|
||||
bool is_optional = IfcSchema::Type::GetAttributeOptional(entity->type(), (unsigned char)i);
|
||||
if (is_optional) {
|
||||
writable_entity()->setArgument(i);
|
||||
} else invalid_argument(i,"NULL");
|
||||
}
|
||||
void IfcParse::IfcLateBoundEntity::setArgumentAsInt(unsigned int i, int v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(entity->type(), (unsigned char)i);
|
||||
if (arg_type == Argument_INT) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else if ( (arg_type == Argument_BOOL) && ( (v == 0) || (v == 1) ) ) {
|
||||
writable_entity()->setArgument(i, v == 1);
|
||||
} else invalid_argument(i,"INTEGER");
|
||||
}
|
||||
void IfcParse::IfcLateBoundEntity::setArgumentAsBool(unsigned int i, bool v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(entity->type(), (unsigned char)i);
|
||||
if (arg_type == Argument_BOOL) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else invalid_argument(i,"BOOLEAN");
|
||||
}
|
||||
void IfcParse::IfcLateBoundEntity::setArgumentAsDouble(unsigned int i, double v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(entity->type(), (unsigned char)i);
|
||||
if (arg_type == Argument_DOUBLE) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else invalid_argument(i,"REAL");
|
||||
}
|
||||
void IfcParse::IfcLateBoundEntity::setArgumentAsString(unsigned int i, const std::string& a) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(entity->type(), (unsigned char)i);
|
||||
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::GetAttributeEntity(entity->type(), (unsigned char)i), a);
|
||||
writable_entity()->setArgument(i, enum_data.second, enum_data.first);
|
||||
} else if (arg_type == Argument_BINARY) {
|
||||
if (valid_binary_string(a)) {
|
||||
boost::dynamic_bitset<> bits(a);
|
||||
writable_entity()->setArgument(i, bits);
|
||||
} else {
|
||||
throw IfcException("String not a valid binary representation");
|
||||
}
|
||||
} else invalid_argument(i,"STRING");
|
||||
}
|
||||
void IfcParse::IfcLateBoundEntity::setArgumentAsAggregateOfInt(unsigned int i, const std::vector<int>& v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(entity->type(), (unsigned char)i);
|
||||
if (arg_type == Argument_AGGREGATE_OF_INT) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else invalid_argument(i,"AGGREGATE OF INT");
|
||||
}
|
||||
void IfcParse::IfcLateBoundEntity::setArgumentAsAggregateOfDouble(unsigned int i, const std::vector<double>& v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(entity->type(), (unsigned char)i);
|
||||
if (arg_type == Argument_AGGREGATE_OF_DOUBLE) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else invalid_argument(i,"AGGREGATE OF DOUBLE");
|
||||
}
|
||||
void IfcParse::IfcLateBoundEntity::setArgumentAsAggregateOfString(unsigned int i, const std::vector<std::string>& v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(entity->type(), (unsigned char)i);
|
||||
if (arg_type == Argument_AGGREGATE_OF_STRING) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else if (arg_type == Argument_AGGREGATE_OF_BINARY) {
|
||||
std::vector< boost::dynamic_bitset<> > bits;
|
||||
bits.reserve(v.size());
|
||||
for (std::vector<std::string>::const_iterator it = v.begin(); it != v.end(); ++it) {
|
||||
if (valid_binary_string(*it)) {
|
||||
bits.push_back(boost::dynamic_bitset<>(*it));
|
||||
} else {
|
||||
throw IfcException("String not a valid binary representation");
|
||||
}
|
||||
}
|
||||
writable_entity()->setArgument(i, bits);
|
||||
} else invalid_argument(i,"AGGREGATE OF STRING");
|
||||
}
|
||||
void IfcParse::IfcLateBoundEntity::setArgumentAsEntityInstance(unsigned int i, IfcParse::IfcLateBoundEntity* v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(entity->type(), (unsigned char)i);
|
||||
if (arg_type == Argument_ENTITY_INSTANCE) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else invalid_argument(i,"ENTITY INSTANCE");
|
||||
}
|
||||
void IfcParse::IfcLateBoundEntity::setArgumentAsAggregateOfEntityInstance(unsigned int i, IfcEntityList::ptr v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(entity->type(), (unsigned char)i);
|
||||
if (arg_type == Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else invalid_argument(i,"AGGREGATE OF ENTITY INSTANCE");
|
||||
}
|
||||
void IfcParse::IfcLateBoundEntity::setArgumentAsAggregateOfAggregateOfInt(unsigned int i, const std::vector< std::vector<int> >& v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(entity->type(), (unsigned char)i);
|
||||
if (arg_type == Argument_AGGREGATE_OF_AGGREGATE_OF_INT) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else invalid_argument(i,"AGGREGATE OF AGGREGATE OF INT");
|
||||
}
|
||||
void IfcParse::IfcLateBoundEntity::setArgumentAsAggregateOfAggregateOfDouble(unsigned int i, const std::vector< std::vector<double> >& v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(entity->type(), (unsigned char)i);
|
||||
if (arg_type == Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else invalid_argument(i,"AGGREGATE OF AGGREGATE OF DOUBLE");
|
||||
}
|
||||
void IfcParse::IfcLateBoundEntity::setArgumentAsAggregateOfAggregateOfEntityInstance(unsigned int i, IfcEntityListList::ptr v) {
|
||||
IfcUtil::ArgumentType arg_type = IfcSchema::Type::GetAttributeType(entity->type(), (unsigned char)i);
|
||||
if (arg_type == Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) {
|
||||
writable_entity()->setArgument(i,v);
|
||||
} else invalid_argument(i,"AGGREGATE OF AGGREGATE OF ENTITY INSTANCE");
|
||||
}
|
||||
unsigned IfcParse::IfcLateBoundEntity::getArgumentIndex(const std::string& a) const {
|
||||
return IfcSchema::Type::GetAttributeIndex(entity->type(),a);
|
||||
}
|
||||
std::string IfcParse::IfcLateBoundEntity::toString() {
|
||||
return entity->toString(false);
|
||||
}
|
||||
IfcEntityList::ptr IfcParse::IfcLateBoundEntity::get_inverse(const std::string& a) {
|
||||
std::pair<IfcSchema::Type::Enum, unsigned> inv = IfcSchema::Type::GetInverseAttribute(entity->type(), a);
|
||||
return entity->getInverse(inv.first, inv.second);
|
||||
}
|
||||
bool IfcParse::IfcLateBoundEntity::is_valid() {
|
||||
const unsigned arg_count = getArgumentCount();
|
||||
bool valid = true;
|
||||
std::ostringstream oss;
|
||||
oss << "Argument ";
|
||||
for (unsigned i = 0; i < arg_count; ++i) {
|
||||
bool is_null = true;
|
||||
try {
|
||||
const Argument& arg = *getArgument(i);
|
||||
is_null = arg.isNull();
|
||||
} catch(IfcException) {}
|
||||
if (!IfcSchema::Type::GetAttributeOptional(entity->type(), (unsigned char)i) && is_null) {
|
||||
if (!valid) {
|
||||
oss << ", ";
|
||||
}
|
||||
oss << "\"" << getArgumentName(i) << "\"";
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
oss << " not optional";
|
||||
if (!valid) {
|
||||
throw IfcException(oss.str());
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
std::vector<std::string> IfcParse::IfcLateBoundEntity::getAttributeNames() const {
|
||||
std::vector<std::string> return_value;
|
||||
return_value.reserve(getArgumentCount());
|
||||
for (unsigned i = 0; i < getArgumentCount(); ++i) {
|
||||
return_value.push_back(getArgumentName(i));
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
|
||||
std::vector<std::string> IfcParse::IfcLateBoundEntity::getInverseAttributeNames() const {
|
||||
std::vector<std::string> return_value;
|
||||
std::set<std::string> values = IfcSchema::Type::GetInverseAttributeNames(entity->type());
|
||||
std::copy(values.begin(), values.end(), std::back_inserter(return_value));
|
||||
return return_value;
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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 <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCLATEBOUNDENTITY_H
|
||||
#define IFCLATEBOUNDENTITY_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ifc_parse_api.h"
|
||||
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcWrite.h"
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
|
||||
namespace IfcParse {
|
||||
|
||||
// TODO: Somehow these methods should become part of IfcBaseEntity directly so
|
||||
// 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 IFC_PARSE_API IfcLateBoundEntity : public IfcUtil::IfcBaseEntity {
|
||||
private:
|
||||
IfcWrite::IfcWritableEntity* writable_entity();
|
||||
void invalid_argument(unsigned int i, const std::string& t);
|
||||
public:
|
||||
IfcLateBoundEntity(const std::string& s);
|
||||
IfcLateBoundEntity(IfcAbstractEntity* e);
|
||||
|
||||
bool is(IfcSchema::Type::Enum v) const;
|
||||
IfcSchema::Type::Enum type() const;
|
||||
bool is_a(const std::string& s) const;
|
||||
std::string is_a() const;
|
||||
|
||||
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;
|
||||
bool getArgumentOptionality(unsigned int i) const;
|
||||
|
||||
IfcEntityList::ptr get_inverse(const std::string& a);
|
||||
|
||||
std::vector<std::string> getAttributeNames() const;
|
||||
std::vector<std::string> getInverseAttributeNames() const;
|
||||
|
||||
void setArgumentAsNull(unsigned int i);
|
||||
void setArgumentAsInt(unsigned int i, int v);
|
||||
void setArgumentAsBool(unsigned int i, bool v);
|
||||
void setArgumentAsDouble(unsigned int i, double v);
|
||||
void setArgumentAsString(unsigned int i, const std::string& v);
|
||||
void setArgumentAsEntityInstance(unsigned int i, IfcLateBoundEntity* v);
|
||||
|
||||
void setArgumentAsAggregateOfInt(unsigned int i, const std::vector<int>& v);
|
||||
void setArgumentAsAggregateOfDouble(unsigned int i, const std::vector<double>& v);
|
||||
void setArgumentAsAggregateOfString(unsigned int i, const std::vector<std::string>& v);
|
||||
void setArgumentAsAggregateOfEntityInstance(unsigned int i, IfcEntityList::ptr v);
|
||||
|
||||
void setArgumentAsAggregateOfAggregateOfInt(unsigned int i, const std::vector< std::vector<int> >& v);
|
||||
void setArgumentAsAggregateOfAggregateOfDouble(unsigned int i, const std::vector< std::vector<double> >& v);
|
||||
void setArgumentAsAggregateOfAggregateOfEntityInstance(unsigned int i, IfcEntityListList::ptr v);
|
||||
|
||||
std::string toString();
|
||||
|
||||
bool is_valid();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -37,7 +37,7 @@ 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, IfcEntityInstanceData* entity) {
|
||||
if ( log2 && type >= verbosity ) {
|
||||
(*log2) << "[" << severity_strings[type] << "] ";
|
||||
if ( current_product ) {
|
||||
|
||||
@@ -54,10 +54,10 @@ 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 Notice(const std::string& message, IfcAbstractEntity* entity = 0) { Message(LOG_NOTICE, message, entity); }
|
||||
static void Warning(const std::string& message, IfcAbstractEntity* entity=0) { Message(LOG_WARNING, message, entity); }
|
||||
static void Error(const std::string& message, IfcAbstractEntity* entity=0) { Message(LOG_ERROR, message, entity); }
|
||||
static void Message(Severity type, const std::string& message, IfcEntityInstanceData* entity=0);
|
||||
static void Notice(const std::string& message, IfcEntityInstanceData* entity = 0) { Message(LOG_NOTICE, message, entity); }
|
||||
static void Warning(const std::string& message, IfcEntityInstanceData* entity=0) { Message(LOG_WARNING, message, entity); }
|
||||
static void Error(const std::string& message, IfcEntityInstanceData* entity=0) { Message(LOG_ERROR, message, entity); }
|
||||
static void Status(const std::string& message, bool new_line=true);
|
||||
static void ProgressBar(int progress);
|
||||
static std::string GetLog();
|
||||
|
||||
+321
-189
@@ -23,6 +23,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctime>
|
||||
#include <boost/circular_buffer.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <Windows.h>
|
||||
@@ -34,13 +35,17 @@
|
||||
#include "../ifcparse/IfcCharacterDecoder.h"
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
#include "../ifcparse/IfcException.h"
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcBaseClass.h"
|
||||
#include "../ifcparse/IfcSpfStream.h"
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
#include "../ifcparse/IfcLateBoundEntity.h"
|
||||
#include "../ifcparse/IfcFile.h"
|
||||
#include "../ifcparse/IfcSIPrefix.h"
|
||||
|
||||
#ifdef USE_IFC4
|
||||
#include "../ifcparse/Ifc4-latebound.h"
|
||||
#else
|
||||
#include "../ifcparse/Ifc2x3-latebound.h"
|
||||
#endif
|
||||
|
||||
#define PERMISSIVE_FLOAT
|
||||
|
||||
using namespace IfcParse;
|
||||
@@ -384,7 +389,7 @@ void IfcSpfLexer::TokenString(unsigned int offset, std::string &buffer) {
|
||||
if ( c == ' ' || c == '\r' || c == '\n' || c == '\t' ) continue;
|
||||
else if ( c == '\'' ) {
|
||||
buffer = *decoder;
|
||||
return;
|
||||
break;
|
||||
}
|
||||
else buffer.push_back(c);
|
||||
}
|
||||
@@ -623,20 +628,18 @@ TokenArgument::TokenArgument(const Token& t) {
|
||||
|
||||
EntityArgument::EntityArgument(const Token& t) {
|
||||
IfcParse::IfcFile* file = t.lexer->file;
|
||||
if (file->create_latebound_entities()) {
|
||||
entity = new IfcLateBoundEntity(new Entity(0, file, t.startPos));
|
||||
} else {
|
||||
entity = IfcSchema::SchemaEntity(new Entity(0, file, t.startPos));
|
||||
}
|
||||
IfcEntityInstanceData* data = read(0, file, t.startPos);
|
||||
entity = IfcSchema::SchemaEntity(data);
|
||||
// Needs to be loaded, for the tokens to be consumed
|
||||
file->load(*data);
|
||||
}
|
||||
|
||||
//
|
||||
// Reads the arguments from a list of token
|
||||
// Aditionally, stores the ids (i.e. #[\d]+) in a vector
|
||||
// Aditionally, registers the ids (i.e. #[\d]+) in the inverse map
|
||||
//
|
||||
void ArgumentList::read(IfcSpfLexer* t, std::vector<unsigned int>& ids) {
|
||||
//IfcParse::IfcFile* file = t->file;
|
||||
Token next = t->Next();
|
||||
void IfcParse::IfcFile::load(unsigned entity_instance_name, std::vector<Argument*>& attributes) {
|
||||
Token next = tokens->Next();
|
||||
while( next.startPos || next.lexer ) {
|
||||
if ( TokenFunc::isOperator(next,',') ) {
|
||||
// do nothing
|
||||
@@ -644,23 +647,25 @@ void ArgumentList::read(IfcSpfLexer* t, std::vector<unsigned int>& ids) {
|
||||
break;
|
||||
} else if ( TokenFunc::isOperator(next,'(') ) {
|
||||
ArgumentList* alist = new ArgumentList();
|
||||
alist->read(t, ids);
|
||||
push(alist);
|
||||
load(entity_instance_name, alist->arguments());
|
||||
attributes.push_back(alist);
|
||||
} else {
|
||||
if ( TokenFunc::isIdentifier(next) ) {
|
||||
ids.push_back(TokenFunc::asIdentifier(next));
|
||||
if (!parsing_complete_) {
|
||||
register_inverse(entity_instance_name, next);
|
||||
}
|
||||
} if ( TokenFunc::isKeyword(next) ) {
|
||||
t->Next();
|
||||
// tokens->Next();
|
||||
try {
|
||||
push ( new EntityArgument(next) );
|
||||
attributes.push_back(new EntityArgument(next));
|
||||
} catch ( IfcException& e ) {
|
||||
Logger::Message(Logger::LOG_ERROR,e.what());
|
||||
Logger::Message(Logger::LOG_ERROR, e.what());
|
||||
}
|
||||
} else {
|
||||
push ( new TokenArgument(next) );
|
||||
attributes.push_back(new TokenArgument(next));
|
||||
}
|
||||
}
|
||||
next = t->Next();
|
||||
next = tokens->Next();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -874,124 +879,99 @@ std::string EntityArgument::toString(bool upper) const {
|
||||
bool EntityArgument::isNull() const { return false; }
|
||||
EntityArgument::~EntityArgument() { delete entity->entity; delete entity;}
|
||||
|
||||
//
|
||||
// Reads an Entity from the list of Tokens
|
||||
//
|
||||
Entity::Entity(unsigned int i, IfcFile* f) : args(0), _id(i) {
|
||||
file = f;
|
||||
Token datatype = f->tokens->Next();
|
||||
if ( ! TokenFunc::isKeyword(datatype)) throw IfcException("Unexpected token while parsing entity");
|
||||
_type = IfcSchema::Type::FromString(TokenFunc::asStringRef(datatype));
|
||||
offset = datatype.startPos;
|
||||
}
|
||||
|
||||
//
|
||||
// Reads an Entity from the list of Tokens at the specified offset in the file
|
||||
//
|
||||
Entity::Entity(unsigned int i, IfcFile* f, unsigned int o) { // : file(f) {
|
||||
file = f;
|
||||
std::vector<unsigned int> ids;
|
||||
_id = i;
|
||||
offset = o;
|
||||
Load(ids, true);
|
||||
}
|
||||
|
||||
//
|
||||
// Access the Nth argument from the ArgumentList
|
||||
//
|
||||
Argument* Entity::getArgument(unsigned int i) {
|
||||
if ( ! args ) {
|
||||
std::vector<unsigned int> ids;
|
||||
Load(ids, true);
|
||||
IfcEntityInstanceData* IfcParse::read(unsigned int i, IfcFile* f, boost::optional<unsigned> offset) {
|
||||
if (offset) {
|
||||
f->tokens->stream->Seek(*offset);
|
||||
}
|
||||
return (*args)[i];
|
||||
Token datatype = f->tokens->Next();
|
||||
if (!TokenFunc::isKeyword(datatype)) throw IfcException("Unexpected token while parsing entity");
|
||||
IfcSchema::Type::Enum ty = IfcSchema::Type::FromString(TokenFunc::asStringRef(datatype));
|
||||
IfcEntityInstanceData* e = new IfcEntityInstanceData(ty, f, i, offset.get_value_or(0));
|
||||
return e;
|
||||
}
|
||||
|
||||
unsigned int Entity::getArgumentCount() const {
|
||||
if ( ! args ) {
|
||||
std::vector<unsigned int> ids;
|
||||
Load(ids, true);
|
||||
void IfcParse::IfcFile::load(const IfcEntityInstanceData& data) {
|
||||
if (tokens->stream->Tell() != data.offset_in_file()) {
|
||||
tokens->stream->Seek(data.offset_in_file());
|
||||
Token datatype = tokens->Next();
|
||||
if (!TokenFunc::isKeyword(datatype)) throw IfcException("Unexpected token while parsing entity instance");
|
||||
}
|
||||
return args->size();
|
||||
}
|
||||
|
||||
//
|
||||
// Load the ArgumentList
|
||||
//
|
||||
void Entity::Load(std::vector<unsigned int>& ids, bool seek) const {
|
||||
if ( seek ) {
|
||||
file->tokens->stream->Seek(offset);
|
||||
Token datatype = file->tokens->Next();
|
||||
if ( ! TokenFunc::isKeyword(datatype)) throw IfcException("Unexpected token while parsing entity");
|
||||
_type = IfcSchema::Type::FromString(TokenFunc::asStringRef(datatype));
|
||||
tokens->Next();
|
||||
load(data.id(), data.attributes());
|
||||
unsigned int old_offset = tokens->stream->Tell();
|
||||
Token semilocon = tokens->Next();
|
||||
if (!TokenFunc::isOperator(semilocon, ';')) {
|
||||
tokens->stream->Seek(old_offset);
|
||||
}
|
||||
/*Token open =*/ file->tokens->Next();
|
||||
args = new ArgumentList();
|
||||
args->read(file->tokens, ids);
|
||||
unsigned int old_offset = file->tokens->stream->Tell();
|
||||
Token semilocon = file->tokens->Next();
|
||||
if ( ! TokenFunc::isOperator(semilocon,';') ) file->tokens->stream->Seek(old_offset);
|
||||
}
|
||||
|
||||
IfcSchema::Type::Enum Entity::type() const {
|
||||
return _type;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the CamelCase string representation of the datatype as it is defined in the schema
|
||||
//
|
||||
std::string Entity::datatype() const {
|
||||
return IfcSchema::Type::ToString(_type);
|
||||
void IfcParse::IfcFile::register_inverse(unsigned id_from, Token t) {
|
||||
// Assume a check on token type has already been performed
|
||||
byref[t.value_int].push_back(id_from);
|
||||
}
|
||||
|
||||
//
|
||||
// Returns a string representation of the entity
|
||||
// Note that this initializes the entity if it is not initialized
|
||||
//
|
||||
std::string Entity::toString(bool upper) const {
|
||||
if (!args) {
|
||||
std::vector<unsigned int> ids;
|
||||
Load(ids, true);
|
||||
std::string IfcEntityInstanceData::toString(bool upper) const {
|
||||
if (!initialized_) {
|
||||
load_();
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
|
||||
std::string dt = datatype();
|
||||
std::string dt = IfcSchema::Type::ToString(type());
|
||||
if (upper) {
|
||||
boost::to_upper(dt);
|
||||
}
|
||||
|
||||
if (!IfcSchema::Type::IsSimple(type()) || _id != 0) {
|
||||
ss << "#" << _id << "=";
|
||||
if (!IfcSchema::Type::IsSimple(type()) || id_ != 0) {
|
||||
ss << "#" << id_ << "=";
|
||||
}
|
||||
|
||||
ss << dt << args->toString(upper);
|
||||
ss << dt << "(";
|
||||
std::vector<Argument*>::const_iterator it = attributes_.begin();
|
||||
for (; it != attributes_.end(); ++it) {
|
||||
if (it != attributes_.begin()) {
|
||||
ss << ",";
|
||||
}
|
||||
ss << (*it)->toString(upper);
|
||||
}
|
||||
ss << ")";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
Entity::~Entity() {
|
||||
delete args;
|
||||
IfcEntityInstanceData::~IfcEntityInstanceData() {
|
||||
std::vector<Argument*>::const_iterator it = attributes_.begin();
|
||||
for (; it != attributes_.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned IfcEntityInstanceData::set_id(boost::optional<unsigned> i) {
|
||||
if (i) {
|
||||
return id_ = *i;
|
||||
} else {
|
||||
return id_ = file->FreshId();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the entities of Entity type that have this entity in their ArgumentList
|
||||
//
|
||||
IfcEntityList::ptr Entity::getInverse(IfcSchema::Type::Enum type, int attribute_index) {
|
||||
return file->getInverse(_id, type, attribute_index);
|
||||
IfcEntityList::ptr IfcEntityInstanceData::getInverse(IfcSchema::Type::Enum type, int attribute_index) {
|
||||
return file->getInverse(id_, type, attribute_index);
|
||||
}
|
||||
|
||||
bool Entity::is(IfcSchema::Type::Enum v) const { return _type == v; }
|
||||
unsigned int Entity::id() { return _id; }
|
||||
|
||||
IfcWrite::IfcWritableEntity* Entity::isWritable() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
IfcFile::IfcFile(bool create_latebound_entities)
|
||||
: _create_latebound_entities(create_latebound_entities)
|
||||
, lastId(0)
|
||||
IfcFile::IfcFile()
|
||||
: parsing_complete_(false)
|
||||
, MaxId(0)
|
||||
, tokens(0)
|
||||
, stream(0)
|
||||
@@ -999,6 +979,147 @@ IfcFile::IfcFile(bool create_latebound_entities)
|
||||
setDefaultHeaderValues();
|
||||
}
|
||||
|
||||
void IfcEntityInstanceData::load_() const {
|
||||
file->load(*this);
|
||||
initialized_ = true;
|
||||
}
|
||||
|
||||
IfcEntityInstanceData::IfcEntityInstanceData(const IfcEntityInstanceData& e) {
|
||||
file = e.file;
|
||||
type_ = e.type_;
|
||||
id_ = 0;
|
||||
|
||||
const unsigned int count = e.getArgumentCount();
|
||||
for (unsigned int i = 0; i < count; ++i) {
|
||||
this->setArgument(i, e.getArgument(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Argument* IfcEntityInstanceData::getArgument(unsigned int i) const {
|
||||
if (!initialized_) {
|
||||
load_();
|
||||
}
|
||||
if (i < attributes_.size()) {
|
||||
return attributes_[i];
|
||||
} else {
|
||||
throw IfcParse::IfcException("Attribute index out of range");
|
||||
}
|
||||
}
|
||||
|
||||
void IfcEntityInstanceData::setArgument(unsigned int i, Argument* a, IfcUtil::ArgumentType attr_type) {
|
||||
while (attributes_.size() < i) {
|
||||
attributes_.push_back(new NullArgument());
|
||||
}
|
||||
|
||||
if (i < attributes_.size()) {
|
||||
delete attributes_[i];
|
||||
}
|
||||
|
||||
if (attr_type == IfcUtil::Argument_UNKNOWN) {
|
||||
attr_type = a->type();
|
||||
}
|
||||
|
||||
IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument();
|
||||
|
||||
switch (attr_type) {
|
||||
case IfcUtil::Argument_NULL:
|
||||
copy->set(boost::blank());
|
||||
break;
|
||||
case IfcUtil::Argument_DERIVED:
|
||||
copy->set(IfcWrite::IfcWriteArgument::Derived());
|
||||
break;
|
||||
case IfcUtil::Argument_INT:
|
||||
copy->set(static_cast<int>(*a));
|
||||
break;
|
||||
case IfcUtil::Argument_BOOL:
|
||||
copy->set(static_cast<bool>(*a));
|
||||
break;
|
||||
case IfcUtil::Argument_DOUBLE:
|
||||
copy->set(static_cast<double>(*a));
|
||||
break;
|
||||
case IfcUtil::Argument_STRING:
|
||||
copy->set(static_cast<std::string>(*a));
|
||||
break;
|
||||
case IfcUtil::Argument_BINARY: {
|
||||
boost::dynamic_bitset<> attr_value = *a;
|
||||
copy->set(attr_value);
|
||||
break; }
|
||||
case IfcUtil::Argument_AGGREGATE_OF_INT: {
|
||||
std::vector<int> attr_value = *a;
|
||||
copy->set(attr_value);
|
||||
break; }
|
||||
case IfcUtil::Argument_AGGREGATE_OF_DOUBLE: {
|
||||
std::vector<double> attr_value = *a;
|
||||
copy->set(attr_value);
|
||||
break; }
|
||||
case IfcUtil::Argument_AGGREGATE_OF_STRING: {
|
||||
std::vector<std::string> attr_value = *a;
|
||||
copy->set(attr_value);
|
||||
break; }
|
||||
case IfcUtil::Argument_AGGREGATE_OF_BINARY: {
|
||||
std::vector< boost::dynamic_bitset<> > attr_value = *a;
|
||||
copy->set(attr_value);
|
||||
break; }
|
||||
case IfcUtil::Argument_ENUMERATION: {
|
||||
IfcSchema::Type::Enum ty = IfcSchema::Type::GetAttributeEntity(type_, (unsigned char)i);
|
||||
std::string enum_literal = a->toString();
|
||||
// Remove leading and trailing '.'
|
||||
enum_literal = enum_literal.substr(1, enum_literal.size() - 2);
|
||||
std::pair<const char*, int> enum_ref = IfcSchema::Type::GetEnumerationIndex(ty, enum_literal);
|
||||
copy->set(IfcWrite::IfcWriteArgument::EnumerationReference(enum_ref.second, enum_ref.first));
|
||||
break; }
|
||||
case IfcUtil::Argument_ENTITY_INSTANCE: {
|
||||
copy->set(static_cast<IfcUtil::IfcBaseClass*>(*a));
|
||||
break; }
|
||||
case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: {
|
||||
IfcEntityList::ptr instances = *a;
|
||||
IfcEntityList::ptr mapped_instances(new IfcEntityList);
|
||||
for (IfcEntityList::it it = instances->begin(); it != instances->end(); ++it) {
|
||||
mapped_instances->push(*it);
|
||||
}
|
||||
copy->set(mapped_instances);
|
||||
break; }
|
||||
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT: {
|
||||
std::vector< std::vector<int> > attr_value = *a;
|
||||
copy->set(attr_value);
|
||||
break; }
|
||||
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE: {
|
||||
std::vector< std::vector<double> > attr_value = *a;
|
||||
copy->set(attr_value);
|
||||
break; }
|
||||
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE: {
|
||||
IfcEntityListList::ptr instances = *a;
|
||||
IfcEntityListList::ptr mapped_instances(new IfcEntityListList);
|
||||
for (IfcEntityListList::outer_it it = instances->begin(); it != instances->end(); ++it) {
|
||||
std::vector<IfcUtil::IfcBaseClass*> inner;
|
||||
for (IfcEntityListList::inner_it jt = it->begin(); jt != it->end(); ++jt) {
|
||||
inner.push_back(*jt);
|
||||
}
|
||||
mapped_instances->push(inner);
|
||||
}
|
||||
copy->set(mapped_instances);
|
||||
break; }
|
||||
case IfcUtil::Argument_EMPTY_AGGREGATE:
|
||||
case IfcUtil::Argument_AGGREGATE_OF_EMPTY_AGGREGATE: {
|
||||
IfcUtil::ArgumentType t2 = IfcSchema::Type::GetAttributeType(type(), (unsigned char)i);
|
||||
delete copy;
|
||||
setArgument(i, a, t2);
|
||||
break; }
|
||||
default:
|
||||
case IfcUtil::Argument_UNKNOWN:
|
||||
throw IfcParse::IfcException(std::string("Unknown attribute encountered: '") + a->toString() + "' at index '" + boost::lexical_cast<std::string>(i) + "'");
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < attributes_.size()) {
|
||||
attributes_[i] = copy;
|
||||
} else {
|
||||
// We have asserted above that the size is at least i
|
||||
attributes_.push_back(copy);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Parses the IFC file in fn
|
||||
// Creates the maps
|
||||
@@ -1026,7 +1147,7 @@ bool IfcFile::Init(IfcParse::IfcSpfStream* s) {
|
||||
}
|
||||
|
||||
tokens = new IfcSpfLexer(stream, this);
|
||||
_header.lexer(tokens);
|
||||
_header.file(this);
|
||||
_header.tryRead();
|
||||
|
||||
std::vector<std::string> schemas;
|
||||
@@ -1037,37 +1158,42 @@ bool IfcFile::Init(IfcParse::IfcSpfStream* s) {
|
||||
Logger::Message(Logger::LOG_ERROR, std::string("File schema encountered different from expected '") + IfcSchema::Identifier + "'");
|
||||
}
|
||||
|
||||
Token token = NoneTokenPtr();
|
||||
Token previous = NoneTokenPtr();
|
||||
boost::circular_buffer<Token> token_stream(3);
|
||||
|
||||
unsigned int currentId = 0;
|
||||
lastId = 0;
|
||||
int x = 0;
|
||||
Entity* e;
|
||||
IfcUtil::IfcBaseClass* entity = 0;
|
||||
IfcEntityInstanceData* data;
|
||||
IfcUtil::IfcBaseClass* instance = 0;
|
||||
|
||||
unsigned current_id = 0;
|
||||
int progress = 0;
|
||||
Logger::Status("Scanning file...");
|
||||
while ( ! stream->eof ) {
|
||||
if ( currentId ) {
|
||||
|
||||
while (!stream->eof) {
|
||||
if (token_stream[0].type == IfcParse::Token_IDENTIFIER &&
|
||||
token_stream[1].type == IfcParse::Token_OPERATOR &&
|
||||
token_stream[1].value_char == '=' &&
|
||||
token_stream[2].type == IfcParse::Token_KEYWORD)
|
||||
{
|
||||
current_id = (unsigned) TokenFunc::asIdentifier(token_stream[0]);
|
||||
IfcSchema::Type::Enum entity_type;
|
||||
try {
|
||||
e = new Entity(currentId,this);
|
||||
if (this->create_latebound_entities()) {
|
||||
entity = new IfcLateBoundEntity(e);
|
||||
} else {
|
||||
entity = IfcSchema::SchemaEntity(e);
|
||||
}
|
||||
entity_type = IfcSchema::Type::FromString(TokenFunc::asStringRef(token_stream[2]));
|
||||
} catch (const IfcException& ex) {
|
||||
currentId = 0;
|
||||
Logger::Message(Logger::LOG_ERROR,ex.what());
|
||||
Logger::Message(Logger::LOG_ERROR, ex.what());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
data = new IfcEntityInstanceData(entity_type, this, current_id, token_stream[2].startPos);
|
||||
instance = IfcSchema::SchemaEntity(data);
|
||||
|
||||
/// @todo Printing to stdout in a library class feels weird. Maybe move the progress prints to the client code?
|
||||
// Update the status after every 1000 instances parsed
|
||||
if ( !((++x)%1000) ) {
|
||||
std::stringstream ss; ss << "\r#" << currentId;
|
||||
if (!((++progress) % 1000)) {
|
||||
std::stringstream ss; ss << "\r#" << current_id;
|
||||
Logger::Status(ss.str(), false);
|
||||
}
|
||||
if ( entity->is(IfcSchema::Type::IfcRoot) ) {
|
||||
IfcSchema::IfcRoot* ifc_root = (IfcSchema::IfcRoot*) entity;
|
||||
|
||||
if (instance->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() ) {
|
||||
@@ -1081,14 +1207,14 @@ bool IfcFile::Init(IfcParse::IfcSpfStream* s) {
|
||||
}
|
||||
}
|
||||
|
||||
IfcSchema::Type::Enum ty = entity->type();
|
||||
IfcSchema::Type::Enum ty = instance->type();
|
||||
for (;;) {
|
||||
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);
|
||||
boost::optional<IfcSchema::Type::Enum> pt = IfcSchema::Type::Parent(ty);
|
||||
if (pt) {
|
||||
ty = *pt;
|
||||
@@ -1097,45 +1223,36 @@ bool IfcFile::Init(IfcParse::IfcSpfStream* s) {
|
||||
}
|
||||
}
|
||||
|
||||
if ( byid.find(currentId) != byid.end() ) {
|
||||
if (byid.find(current_id) != byid.end()) {
|
||||
std::stringstream ss;
|
||||
ss << "Overwriting instance with name #" << currentId;
|
||||
ss << "Overwriting instance with name #" << current_id;
|
||||
Logger::Message(Logger::LOG_WARNING,ss.str());
|
||||
}
|
||||
byid[currentId] = entity;
|
||||
byid[current_id] = instance;
|
||||
|
||||
MaxId = (std::max)(MaxId,currentId);
|
||||
currentId = 0;
|
||||
} else {
|
||||
try {
|
||||
token = tokens->Next();
|
||||
} catch (const IfcException& e) {
|
||||
Logger::Message(Logger::LOG_ERROR, std::string(e.what()) + ". Parsing terminated");
|
||||
token = NoneTokenPtr();
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Parsing terminated");
|
||||
token = NoneTokenPtr();
|
||||
}
|
||||
MaxId = (std::max)(MaxId, current_id);
|
||||
} else if (token_stream[0].type == IfcParse::Token_IDENTIFIER && instance) {
|
||||
register_inverse(current_id, token_stream[0]);
|
||||
}
|
||||
|
||||
if ( ! (token.startPos || token.lexer) ) break;
|
||||
|
||||
if ( (previous.startPos || previous.lexer) && TokenFunc::isIdentifier(previous) ) {
|
||||
int id = TokenFunc::asIdentifier(previous);
|
||||
if ( TokenFunc::isOperator(token,'=') ) {
|
||||
currentId = id;
|
||||
} else if (entity) {
|
||||
IfcEntityList::ptr instances_by_ref = entitiesByReference(id);
|
||||
if (!instances_by_ref) {
|
||||
instances_by_ref = IfcEntityList::ptr(new IfcEntityList());
|
||||
byref[id] = instances_by_ref;
|
||||
}
|
||||
instances_by_ref->push(entity);
|
||||
}
|
||||
Token next_token;
|
||||
try {
|
||||
next_token = tokens->Next();
|
||||
} catch (const IfcException& e) {
|
||||
Logger::Message(Logger::LOG_ERROR, std::string(e.what()) + ". Parsing terminated");
|
||||
} catch (...) {
|
||||
Logger::Message(Logger::LOG_ERROR, "Parsing terminated");
|
||||
}
|
||||
previous = token;
|
||||
|
||||
if (next_token.type == Token_NONE) break;
|
||||
|
||||
token_stream.push_back(next_token);
|
||||
}
|
||||
|
||||
Logger::Status("\rDone scanning file ");
|
||||
|
||||
parsing_complete_ = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1215,12 +1332,8 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
// 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);
|
||||
}
|
||||
IfcEntityInstanceData* we = new IfcEntityInstanceData(*entity->entity);
|
||||
entity = IfcSchema::SchemaEntity(we);
|
||||
|
||||
// In case an entity is added that contains geometry, the unit
|
||||
// information needs to be accounted for for IfcLengthMeasures.
|
||||
@@ -1232,7 +1345,10 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
if (attr_type == IfcUtil::Argument_ENTITY_INSTANCE) {
|
||||
entity_entity_map_t::const_iterator eit = entity_file_map.find(*attr);
|
||||
if (eit == entity_file_map.end()) throw IfcParse::IfcException("Unable to map instance to file");
|
||||
we->setArgument(i, eit->second);
|
||||
|
||||
IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument();
|
||||
copy->set(eit->second);
|
||||
we->setArgument(i, copy);
|
||||
} else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
|
||||
IfcEntityList::ptr instances = *attr;
|
||||
IfcEntityList::ptr new_instances(new IfcEntityList);
|
||||
@@ -1241,7 +1357,10 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
if (eit == entity_file_map.end()) throw IfcParse::IfcException("Unable to map instance to file");
|
||||
new_instances->push(eit->second);
|
||||
}
|
||||
we->setArgument(i, new_instances);
|
||||
|
||||
IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument();
|
||||
copy->set(new_instances);
|
||||
we->setArgument(i, copy);
|
||||
} else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) {
|
||||
IfcEntityListList::ptr instances = *attr;
|
||||
IfcEntityListList::ptr new_instances(new IfcEntityListList);
|
||||
@@ -1254,7 +1373,11 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
}
|
||||
new_instances->push(list);
|
||||
}
|
||||
we->setArgument(i, new_instances);
|
||||
|
||||
IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument();
|
||||
copy->set(new_instances);
|
||||
we->setArgument(i, copy);
|
||||
|
||||
} else if (entity->getArgumentEntity(i) == IfcSchema::Type::IfcLengthMeasure ||
|
||||
entity->getArgumentEntity(i) == IfcSchema::Type::IfcPositiveLengthMeasure)
|
||||
{
|
||||
@@ -1265,13 +1388,19 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
if (attr_type == IfcUtil::Argument_DOUBLE) {
|
||||
double v = *attr;
|
||||
v *= conversion_factor;
|
||||
we->setArgument(i, v);
|
||||
|
||||
IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument();
|
||||
copy->set(v);
|
||||
we->setArgument(i, copy);
|
||||
} 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);
|
||||
|
||||
IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument();
|
||||
copy->set(v);
|
||||
we->setArgument(i, copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1279,7 +1408,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
// A new entity instance name is generated and
|
||||
// the instance is pointed to this file.
|
||||
we->file = this;
|
||||
we->setId(FreshId());
|
||||
we->set_id(FreshId());
|
||||
}
|
||||
|
||||
// For subtypes of IfcRoot, the GUID mapping needs to be updated.
|
||||
@@ -1317,10 +1446,10 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
}
|
||||
|
||||
int new_id = -1;
|
||||
if (entity->entity->isWritable() && !entity->entity->file) {
|
||||
if (!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();
|
||||
new_id = entity->entity->set_id();
|
||||
} else {
|
||||
new_id = entity->entity->id();
|
||||
}
|
||||
@@ -1346,12 +1475,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
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);
|
||||
byref[entity_attribute_id].push_back(entity->entity->id());
|
||||
}
|
||||
} catch (const IfcParse::IfcException&) {}
|
||||
}
|
||||
@@ -1359,16 +1483,6 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
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);
|
||||
@@ -1403,14 +1517,19 @@ void IfcFile::removeEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
case IfcUtil::Argument_ENTITY_INSTANCE: {
|
||||
IfcUtil::IfcBaseClass* instance_attribute = *attr;
|
||||
if (instance_attribute == entity) {
|
||||
make_writable(related_instance)->setArgument(i);
|
||||
IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument();
|
||||
copy->set(boost::blank());
|
||||
related_instance->entity->setArgument(i, copy);
|
||||
} }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: {
|
||||
IfcEntityList::ptr instance_list = *attr;
|
||||
if (instance_list->contains(entity)) {
|
||||
instance_list->remove(entity);
|
||||
make_writable(related_instance)->setArgument(i, instance_list);
|
||||
|
||||
IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument();
|
||||
copy->set(instance_list);
|
||||
related_instance->entity->setArgument(i, copy);
|
||||
} }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE: {
|
||||
@@ -1425,7 +1544,10 @@ void IfcFile::removeEntity(IfcUtil::IfcBaseClass* entity) {
|
||||
}
|
||||
new_list->push(instances);
|
||||
}
|
||||
make_writable(related_instance)->setArgument(i, new_list);
|
||||
|
||||
IfcWrite::IfcWriteArgument* copy = new IfcWrite::IfcWriteArgument();
|
||||
copy->set(new_list);
|
||||
related_instance->entity->setArgument(i, copy);
|
||||
} }
|
||||
break;
|
||||
default: break;
|
||||
@@ -1474,7 +1596,17 @@ IfcEntityList::ptr IfcFile::entitiesByType(const std::string& t) {
|
||||
|
||||
IfcEntityList::ptr IfcFile::entitiesByReference(int t) {
|
||||
entities_by_ref_t::const_iterator it = byref.find(t);
|
||||
return (it == byref.end()) ? IfcEntityList::ptr() : it->second;
|
||||
IfcEntityList::ptr return_value;
|
||||
if (it != byref.end()) {
|
||||
const std::vector<unsigned>& ids = it->second;
|
||||
for (std::vector<unsigned>::const_iterator jt = ids.begin(); jt != ids.end(); ++jt) {
|
||||
if (!return_value) {
|
||||
return_value.reset(new IfcEntityList);
|
||||
}
|
||||
return_value->push(entityById(*jt));
|
||||
}
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
|
||||
IfcUtil::IfcBaseClass* IfcFile::entityById(int id) {
|
||||
|
||||
+10
-34
@@ -43,8 +43,9 @@
|
||||
#include "ifc_parse_api.h"
|
||||
|
||||
#include "../ifcparse/IfcCharacterDecoder.h"
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcBaseClass.h"
|
||||
#include "../ifcparse/IfcLogger.h"
|
||||
#include "../ifcparse/Argument.h"
|
||||
|
||||
#ifdef USE_IFC4
|
||||
#include "../ifcparse/Ifc4.h"
|
||||
@@ -56,7 +57,6 @@
|
||||
|
||||
namespace IfcParse {
|
||||
|
||||
class Entity;
|
||||
class IfcFile;
|
||||
class IfcSpfLexer;
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace IfcParse {
|
||||
|
||||
struct Token {
|
||||
IfcSpfLexer* lexer; //TODO: remove it from here
|
||||
unsigned startPos, endPos;
|
||||
unsigned startPos;
|
||||
TokenType type;
|
||||
union {
|
||||
bool value_bool; //types: BOOL
|
||||
@@ -84,9 +84,9 @@ namespace IfcParse {
|
||||
double value_double; //types: FLOAT
|
||||
};
|
||||
|
||||
Token() : lexer(0), startPos(0), endPos(0), type(Token_NONE) {}
|
||||
Token(IfcSpfLexer* _lexer, unsigned _startPos, unsigned _endPos, TokenType _type)
|
||||
: lexer(_lexer), startPos(_startPos), endPos(_endPos), type(_type) {}
|
||||
Token() : lexer(0), startPos(0), type(Token_NONE) {}
|
||||
Token(IfcSpfLexer* _lexer, unsigned _startPos, unsigned /*_endPos*/, TokenType _type)
|
||||
: lexer(_lexer), startPos(_startPos), type(_type) {}
|
||||
};
|
||||
|
||||
/// Provides functions to convert Tokens to binary data
|
||||
@@ -192,6 +192,8 @@ namespace IfcParse {
|
||||
void set(unsigned int i, Argument*);
|
||||
|
||||
std::string toString(bool upper=false) const;
|
||||
|
||||
std::vector<Argument*>& arguments() { return list; }
|
||||
};
|
||||
|
||||
|
||||
@@ -253,34 +255,8 @@ namespace IfcParse {
|
||||
Argument* operator [] (unsigned int i) const;
|
||||
std::string toString(bool upper=false) const;
|
||||
};
|
||||
|
||||
/// Entity defined in an IFC file, e.g.
|
||||
/// #1=IfcDirection((1.,0.,0.));
|
||||
/// ============================
|
||||
class IFC_PARSE_API Entity : public IfcAbstractEntity {
|
||||
private:
|
||||
mutable ArgumentList* args;
|
||||
mutable IfcSchema::Type::Enum _type;
|
||||
public:
|
||||
/// The EXPRESS ENTITY_INSTANCE_NAME
|
||||
unsigned int _id;
|
||||
/// The offset at which the entity is read
|
||||
unsigned int offset;
|
||||
Entity(unsigned int i, IfcFile* t);
|
||||
Entity(unsigned int i, IfcFile* t, unsigned int o);
|
||||
virtual ~Entity();
|
||||
IfcEntityList::ptr getInverse(IfcSchema::Type::Enum type, int attribute_index);
|
||||
void Load(std::vector<unsigned int>& ids, bool seek=false) const;
|
||||
Argument* getArgument (unsigned int i);
|
||||
unsigned int getArgumentCount() const;
|
||||
std::string toString(bool upper=false) const;
|
||||
std::string datatype() const;
|
||||
IfcSchema::Type::Enum type() const;
|
||||
bool is(IfcSchema::Type::Enum v) const;
|
||||
unsigned int id();
|
||||
IfcWrite::IfcWritableEntity* isWritable();
|
||||
};
|
||||
|
||||
|
||||
IfcEntityInstanceData* read(unsigned int i, IfcFile* t, boost::optional<unsigned> offset = boost::none);
|
||||
}
|
||||
|
||||
IFC_PARSE_API std::ostream& operator<< (std::ostream& os, const IfcParse::IfcFile& f);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
#include "../ifcparse/IfcFile.h"
|
||||
|
||||
#include "IfcSpfHeader.h"
|
||||
|
||||
@@ -35,20 +35,30 @@ static const char * const DATA = "DATA";
|
||||
|
||||
using namespace IfcParse;
|
||||
|
||||
HeaderEntity::HeaderEntity(const char * const datatype, IfcFile* file)
|
||||
: IfcEntityInstanceData(IfcSchema::Type::UNDEFINED, file), _datatype(datatype)
|
||||
{
|
||||
if (file) {
|
||||
offset_in_file_ = file->stream->Tell();
|
||||
load_();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void IfcSpfHeader::readSemicolon() {
|
||||
if (!TokenFunc::isOperator(_lexer->Next(), ';')) {
|
||||
if (!TokenFunc::isOperator(file_->tokens->Next(), ';')) {
|
||||
throw IfcException(std::string("Expected ;"));
|
||||
}
|
||||
}
|
||||
|
||||
void IfcSpfHeader::readParen() {
|
||||
if (!TokenFunc::isOperator(_lexer->Next(), '(')) {
|
||||
if (!TokenFunc::isOperator(file_->tokens->Next(), '(')) {
|
||||
throw IfcException(std::string("Expected ("));
|
||||
}
|
||||
}
|
||||
|
||||
void IfcSpfHeader::readTerminal(const std::string& term, Trail trail) {
|
||||
if (TokenFunc::asStringRef(_lexer->Next()) != term) {
|
||||
if (TokenFunc::asStringRef(file_->tokens->Next()) != term) {
|
||||
throw IfcException(std::string("Expected " + term));
|
||||
}
|
||||
if (trail == TRAILING_SEMICOLON) {
|
||||
@@ -72,20 +82,20 @@ void IfcSpfHeader::read() {
|
||||
//
|
||||
// ISO 10303-21 Second edition 2002-01-15 p. 16
|
||||
|
||||
readTerminal(FILE_DESCRIPTION, TRAILING_PAREN);
|
||||
readTerminal(FILE_DESCRIPTION, NONE);
|
||||
delete _file_description;
|
||||
_file_description = new FileDescription(_lexer);
|
||||
readSemicolon();
|
||||
_file_description = new FileDescription(file_);
|
||||
// readSemicolon();
|
||||
|
||||
readTerminal(FILE_NAME, TRAILING_PAREN);
|
||||
readTerminal(FILE_NAME, NONE);
|
||||
delete _file_name;
|
||||
_file_name = new FileName(_lexer);
|
||||
readSemicolon();
|
||||
_file_name = new FileName(file_);
|
||||
// readSemicolon();
|
||||
|
||||
readTerminal(FILE_SCHEMA, TRAILING_PAREN);
|
||||
readTerminal(FILE_SCHEMA, NONE);
|
||||
delete _file_schema;
|
||||
_file_schema = new FileSchema(_lexer);
|
||||
readSemicolon();
|
||||
_file_schema = new FileSchema(file_);
|
||||
// readSemicolon();
|
||||
}
|
||||
|
||||
bool IfcSpfHeader::tryRead() {
|
||||
@@ -155,6 +165,6 @@ FileSchema& IfcSpfHeader::file_schema() {
|
||||
}
|
||||
}
|
||||
|
||||
FileDescription::FileDescription(IfcSpfLexer* lexer) : HeaderEntity(FILE_DESCRIPTION, lexer) {}
|
||||
FileName::FileName(IfcSpfLexer* lexer) : HeaderEntity(FILE_NAME, lexer) {}
|
||||
FileSchema::FileSchema(IfcSpfLexer* lexer) : HeaderEntity(FILE_SCHEMA, lexer) {}
|
||||
FileDescription::FileDescription(IfcFile* file) : HeaderEntity(FILE_DESCRIPTION, file) {}
|
||||
FileName::FileName(IfcFile* file) : HeaderEntity(FILE_NAME, file) {}
|
||||
FileSchema::FileSchema(IfcFile* file) : HeaderEntity(FILE_SCHEMA, file) {}
|
||||
+37
-76
@@ -27,98 +27,59 @@
|
||||
|
||||
namespace IfcParse {
|
||||
|
||||
class IFC_PARSE_API HeaderEntity : public IfcAbstractEntity {
|
||||
class IFC_PARSE_API HeaderEntity : public IfcEntityInstanceData {
|
||||
private:
|
||||
ArgumentList* _list;
|
||||
const char * const _datatype;
|
||||
|
||||
HeaderEntity(const HeaderEntity&); //N/A
|
||||
HeaderEntity& operator =(const HeaderEntity&); //N/A
|
||||
protected:
|
||||
HeaderEntity(const char * const datatype, IfcSpfLexer* lexer)
|
||||
: _list(0), _datatype(datatype)
|
||||
{
|
||||
std::vector<unsigned int> ids;
|
||||
_list = new ArgumentList();
|
||||
if (lexer) {
|
||||
_list->read(lexer, ids);
|
||||
}
|
||||
}
|
||||
HeaderEntity(const char * const datatype, IfcParse::IfcFile* file);
|
||||
|
||||
virtual ~HeaderEntity() {
|
||||
delete _list;
|
||||
}
|
||||
|
||||
void setArgument(unsigned int i, const std::string& s) {
|
||||
void setValue(unsigned int i, const std::string& s) {
|
||||
IfcWrite::IfcWriteArgument* argument = new IfcWrite::IfcWriteArgument;
|
||||
argument->set(s);
|
||||
_list->set(i, argument);
|
||||
setArgument(i, argument);
|
||||
}
|
||||
|
||||
void setArgument(unsigned int i, const std::vector<std::string>& s) {
|
||||
void setValue(unsigned int i, const std::vector<std::string>& s) {
|
||||
IfcWrite::IfcWriteArgument* argument = new IfcWrite::IfcWriteArgument;
|
||||
argument->set(s);
|
||||
_list->set(i, argument);
|
||||
setArgument(i, argument);
|
||||
}
|
||||
|
||||
public:
|
||||
Argument* getArgument(unsigned int i) const {
|
||||
return (*_list)[i];
|
||||
}
|
||||
|
||||
Argument* getArgument(unsigned int i) {
|
||||
return (*_list)[i];
|
||||
}
|
||||
|
||||
IfcEntityList::ptr getInverse(IfcSchema::Type::Enum /*type*/, int /*attribute_index*/) {
|
||||
return IfcEntityList::ptr(new IfcEntityList);
|
||||
}
|
||||
|
||||
std::string datatype() const {
|
||||
return _datatype;
|
||||
}
|
||||
|
||||
unsigned int getArgumentCount() const {
|
||||
return _list->size();
|
||||
}
|
||||
|
||||
IfcSchema::Type::Enum type() const {
|
||||
return (IfcSchema::Type::Enum) -1;
|
||||
}
|
||||
|
||||
bool is(IfcSchema::Type::Enum /*v*/) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string toString(bool upper=false) const {
|
||||
std::stringstream ss;
|
||||
ss << _datatype << _list->toString(upper) << ";";
|
||||
// Unfortunately this is duplicated from IfcEntityInstanceData::toString()
|
||||
ss << _datatype << "(";
|
||||
std::vector<Argument*>::const_iterator it = attributes_.begin();
|
||||
for (; it != attributes_.end(); ++it) {
|
||||
if (it != attributes_.begin()) {
|
||||
ss << ",";
|
||||
}
|
||||
ss << (*it)->toString(upper);
|
||||
}
|
||||
ss << ")";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
unsigned int id() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
IfcWrite::IfcWritableEntity* isWritable() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
class IFC_PARSE_API FileDescription : public HeaderEntity {
|
||||
public:
|
||||
explicit FileDescription(IfcSpfLexer* = 0);
|
||||
explicit FileDescription(IfcFile* = 0);
|
||||
|
||||
std::vector<std::string> description() const { return *getArgument(0); }
|
||||
std::string implementation_level() const { return *getArgument(1); }
|
||||
|
||||
void description(const std::vector<std::string>& value) { setArgument(0, value); }
|
||||
void implementation_level(const std::string& value) { setArgument(1, value); }
|
||||
void description(const std::vector<std::string>& value) { setValue(0, value); }
|
||||
void implementation_level(const std::string& value) { setValue(1, value); }
|
||||
};
|
||||
|
||||
class IFC_PARSE_API FileName : public HeaderEntity {
|
||||
public:
|
||||
explicit FileName(IfcSpfLexer* = 0);
|
||||
explicit FileName(IfcFile* = 0);
|
||||
|
||||
std::string name() const { return *getArgument(0); }
|
||||
std::string time_stamp() const { return *getArgument(1); }
|
||||
@@ -128,27 +89,27 @@ public:
|
||||
std::string originating_system() const { return *getArgument(5); }
|
||||
std::string authorization() const { return *getArgument(6); }
|
||||
|
||||
void name(const std::string& value) { setArgument(0, value); }
|
||||
void time_stamp(const std::string& value) { setArgument(1, value); }
|
||||
void author(const std::vector<std::string>& value) { setArgument(2, value); }
|
||||
void organization(const std::vector<std::string>& value) { setArgument(3, value); }
|
||||
void preprocessor_version(const std::string& value) { setArgument(4, value); }
|
||||
void originating_system(const std::string& value) { setArgument(5, value); }
|
||||
void authorization(const std::string& value) { setArgument(6, value); }
|
||||
void name(const std::string& value) { setValue(0, value); }
|
||||
void time_stamp(const std::string& value) { setValue(1, value); }
|
||||
void author(const std::vector<std::string>& value) { setValue(2, value); }
|
||||
void organization(const std::vector<std::string>& value) { setValue(3, value); }
|
||||
void preprocessor_version(const std::string& value) { setValue(4, value); }
|
||||
void originating_system(const std::string& value) { setValue(5, value); }
|
||||
void authorization(const std::string& value) { setValue(6, value); }
|
||||
};
|
||||
|
||||
class IFC_PARSE_API FileSchema : public HeaderEntity {
|
||||
public:
|
||||
explicit FileSchema(IfcSpfLexer* = 0);
|
||||
explicit FileSchema(IfcFile* = 0);
|
||||
|
||||
std::vector<std::string> schema_identifiers() const { return *getArgument(0); }
|
||||
|
||||
void schema_identifiers(const std::vector<std::string>& value) { setArgument(0, value); }
|
||||
void schema_identifiers(const std::vector<std::string>& value) { setValue(0, value); }
|
||||
};
|
||||
|
||||
class IFC_PARSE_API IfcSpfHeader {
|
||||
private:
|
||||
IfcSpfLexer* _lexer;
|
||||
IfcFile* file_;
|
||||
FileDescription* _file_description;
|
||||
FileName* _file_name;
|
||||
FileSchema* _file_schema;
|
||||
@@ -161,12 +122,12 @@ private:
|
||||
};
|
||||
void readTerminal(const std::string& term, Trail trail);
|
||||
public:
|
||||
explicit IfcSpfHeader(IfcSpfLexer* lexer = 0)
|
||||
: _lexer(lexer), _file_description(0), _file_name(0), _file_schema(0)
|
||||
explicit IfcSpfHeader(IfcParse::IfcFile* file = 0)
|
||||
: file_(file), _file_description(0), _file_name(0), _file_schema(0)
|
||||
{
|
||||
_file_description = new FileDescription();
|
||||
_file_name = new FileName();
|
||||
_file_schema = new FileSchema();
|
||||
_file_description = new FileDescription(file_);
|
||||
_file_name = new FileName(file_);
|
||||
_file_schema = new FileSchema(file_);
|
||||
}
|
||||
|
||||
~IfcSpfHeader()
|
||||
@@ -176,8 +137,8 @@ public:
|
||||
delete _file_description;
|
||||
}
|
||||
|
||||
IfcSpfLexer* lexer() { return _lexer; }
|
||||
void lexer(IfcSpfLexer* l) { _lexer = l; }
|
||||
IfcParse::IfcFile* file() { return file_; }
|
||||
void file(IfcParse::IfcFile * file) { file_ = file; }
|
||||
|
||||
void read();
|
||||
bool tryRead();
|
||||
|
||||
@@ -17,8 +17,16 @@
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "IfcUtil.h"
|
||||
#include "../ifcparse/IfcBaseClass.h"
|
||||
#include "../ifcparse/Argument.h"
|
||||
#include "../ifcparse/IfcException.h"
|
||||
#include "../ifcparse/IfcEntityList.h"
|
||||
|
||||
#ifdef USE_IFC4
|
||||
#include "../ifcparse/Ifc4-latebound.h"
|
||||
#else
|
||||
#include "../ifcparse/Ifc2x3-latebound.h"
|
||||
#endif
|
||||
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
@@ -155,3 +163,24 @@ void IfcUtil::unescape_xml(std::string &str)
|
||||
boost::replace_all(str, ">", ">");
|
||||
boost::replace_all(str, "&", "&");
|
||||
}
|
||||
|
||||
std::vector<std::string> IfcUtil::IfcBaseEntity::getAttributeNames() const {
|
||||
std::vector<std::string> return_value;
|
||||
return_value.reserve(getArgumentCount());
|
||||
for (unsigned i = 0; i < getArgumentCount(); ++i) {
|
||||
return_value.push_back(getArgumentName(i));
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
|
||||
std::vector<std::string> IfcUtil::IfcBaseEntity::getInverseAttributeNames() const {
|
||||
std::vector<std::string> return_value;
|
||||
std::set<std::string> values = IfcSchema::Type::GetInverseAttributeNames(entity->type());
|
||||
std::copy(values.begin(), values.end(), std::back_inserter(return_value));
|
||||
return return_value;
|
||||
}
|
||||
|
||||
Argument* IfcUtil::IfcBaseEntity::getArgumentByName(const std::string& name) const {
|
||||
unsigned int i = IfcSchema::Type::GetAttributeIndex(type(), name);
|
||||
return getArgument(i);
|
||||
}
|
||||
|
||||
@@ -1,332 +0,0 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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 <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCUTIL_H
|
||||
#define IFCUTIL_H
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "ifc_parse_api.h"
|
||||
|
||||
#ifdef USE_IFC4
|
||||
#include "../ifcparse/Ifc4enum.h"
|
||||
#else
|
||||
#include "../ifcparse/Ifc2x3enum.h"
|
||||
#endif
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/dynamic_bitset.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#define foreach BOOST_FOREACH
|
||||
#define rforeach BOOST_REVERSE_FOREACH
|
||||
|
||||
class Argument;
|
||||
class IfcEntityList;
|
||||
class IfcEntityListList;
|
||||
class IfcAbstractEntity;
|
||||
namespace IfcWrite {
|
||||
class IfcWritableEntity;
|
||||
}
|
||||
|
||||
namespace IfcUtil {
|
||||
enum ArgumentType {
|
||||
Argument_NULL,
|
||||
Argument_DERIVED,
|
||||
Argument_INT,
|
||||
Argument_BOOL,
|
||||
Argument_DOUBLE,
|
||||
Argument_STRING,
|
||||
Argument_BINARY,
|
||||
Argument_ENUMERATION,
|
||||
Argument_ENTITY_INSTANCE,
|
||||
|
||||
Argument_EMPTY_AGGREGATE,
|
||||
Argument_AGGREGATE_OF_INT,
|
||||
Argument_AGGREGATE_OF_DOUBLE,
|
||||
Argument_AGGREGATE_OF_STRING,
|
||||
Argument_AGGREGATE_OF_BINARY,
|
||||
Argument_AGGREGATE_OF_ENTITY_INSTANCE,
|
||||
|
||||
Argument_AGGREGATE_OF_EMPTY_AGGREGATE,
|
||||
Argument_AGGREGATE_OF_AGGREGATE_OF_INT,
|
||||
Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE,
|
||||
Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE,
|
||||
|
||||
Argument_UNKNOWN
|
||||
};
|
||||
|
||||
|
||||
IFC_PARSE_API const char* ArgumentTypeToString(ArgumentType argument_type);
|
||||
|
||||
class IFC_PARSE_API IfcBaseClass {
|
||||
public:
|
||||
virtual ~IfcBaseClass() {}
|
||||
IfcAbstractEntity* entity;
|
||||
virtual bool is(IfcSchema::Type::Enum v) const = 0;
|
||||
virtual IfcSchema::Type::Enum type() const = 0;
|
||||
|
||||
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;
|
||||
|
||||
template <class T>
|
||||
T* as() {
|
||||
return is(T::Class())
|
||||
? static_cast<T*>(this)
|
||||
: static_cast<T*>(0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const T* as() const {
|
||||
return is(T::Class())
|
||||
? static_cast<const T*>(this)
|
||||
: static_cast<const T*>(0);
|
||||
}
|
||||
};
|
||||
|
||||
class IFC_PARSE_API IfcBaseEntity : public IfcBaseClass {
|
||||
};
|
||||
|
||||
// TODO: Investigate whether these should be template classes instead
|
||||
class IFC_PARSE_API IfcBaseType : public IfcBaseEntity {
|
||||
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; }
|
||||
};
|
||||
|
||||
IFC_PARSE_API bool valid_binary_string(const std::string& s);
|
||||
/// Replaces spaces and potentially other problem causing characters with underscores.
|
||||
IFC_PARSE_API void sanitate_material_name(std::string &str);
|
||||
IFC_PARSE_API void escape_xml(std::string &str);
|
||||
IFC_PARSE_API void unescape_xml(std::string &str);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class IfcTemplatedEntityList;
|
||||
|
||||
class IFC_PARSE_API IfcEntityList {
|
||||
std::vector<IfcUtil::IfcBaseClass*> ls;
|
||||
public:
|
||||
typedef boost::shared_ptr<IfcEntityList> ptr;
|
||||
typedef std::vector<IfcUtil::IfcBaseClass*>::const_iterator it;
|
||||
void push(IfcUtil::IfcBaseClass* l);
|
||||
void push(const ptr& l);
|
||||
it begin();
|
||||
it end();
|
||||
IfcUtil::IfcBaseClass* operator[] (int i);
|
||||
unsigned int size() const;
|
||||
bool contains(IfcUtil::IfcBaseClass*) const;
|
||||
template <class U>
|
||||
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);
|
||||
return r;
|
||||
}
|
||||
void remove(IfcUtil::IfcBaseClass*);
|
||||
IfcEntityList::ptr filtered(const std::set<IfcSchema::Type::Enum>& entities);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class IfcTemplatedEntityList {
|
||||
std::vector<T*> ls;
|
||||
public:
|
||||
typedef boost::shared_ptr< IfcTemplatedEntityList<T> > ptr;
|
||||
typedef typename std::vector<T*>::const_iterator it;
|
||||
void push(T* t) { if (t) { ls.push_back(t); } }
|
||||
void push(ptr t) { if (t) { for ( typename T::list::it it = t->begin(); it != t->end(); ++it ) push(*it); } }
|
||||
it begin() { return ls.begin(); }
|
||||
it end() { return ls.end(); }
|
||||
unsigned int size() const { return (unsigned int) ls.size(); }
|
||||
IfcEntityList::ptr generalize() {
|
||||
IfcEntityList::ptr r (new IfcEntityList());
|
||||
for ( it i = begin(); i != end(); ++ i ) r->push(*i);
|
||||
return r;
|
||||
}
|
||||
bool contains(T* t) const { return std::find(ls.begin(), ls.end(), t) != ls.end(); }
|
||||
template <class U>
|
||||
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);
|
||||
return r;
|
||||
}
|
||||
void remove(T* t) {
|
||||
typename std::vector<T*>::iterator it;
|
||||
while ((it = std::find(ls.begin(), ls.end(), t)) != ls.end()) {
|
||||
ls.erase(it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class IfcTemplatedEntityListList;
|
||||
|
||||
class IFC_PARSE_API IfcEntityListList {
|
||||
std::vector< std::vector<IfcUtil::IfcBaseClass*> > ls;
|
||||
public:
|
||||
typedef boost::shared_ptr< IfcEntityListList > ptr;
|
||||
typedef std::vector< std::vector<IfcUtil::IfcBaseClass*> >::const_iterator outer_it;
|
||||
typedef std::vector<IfcUtil::IfcBaseClass*>::const_iterator inner_it;
|
||||
void push(const std::vector<IfcUtil::IfcBaseClass*>& l) {
|
||||
ls.push_back(l);
|
||||
}
|
||||
void push(const IfcEntityList::ptr& l) {
|
||||
if (l) {
|
||||
std::vector<IfcUtil::IfcBaseClass*> li;
|
||||
for (std::vector<IfcUtil::IfcBaseClass*>::const_iterator jt = l->begin(); jt != l->end(); ++jt) {
|
||||
li.push_back(*jt);
|
||||
}
|
||||
push(li);
|
||||
}
|
||||
}
|
||||
outer_it begin() const { return ls.begin(); }
|
||||
outer_it end() const { return ls.end(); }
|
||||
int size() const { return (int)ls.size(); }
|
||||
int totalSize() const {
|
||||
int accum = 0;
|
||||
for (outer_it it = begin(); it != end(); ++it) {
|
||||
accum += (int)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;
|
||||
if (std::find(inner.begin(), inner.end(), instance) != inner.end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template <class U>
|
||||
typename IfcTemplatedEntityListList<U>::ptr as() {
|
||||
typename IfcTemplatedEntityListList<U>::ptr r(new IfcTemplatedEntityListList<U>);
|
||||
const bool all = U::Class() == IfcSchema::Type::UNDEFINED;
|
||||
for (outer_it outer = begin(); outer != end(); ++ outer) {
|
||||
const std::vector<IfcUtil::IfcBaseClass*>& from = *outer;
|
||||
typename std::vector<U*> to;
|
||||
for (inner_it inner = from.begin(); inner != from.end(); ++ inner) {
|
||||
if (all || (*inner)->is(U::Class())) to.push_back((U*)*inner);
|
||||
}
|
||||
r->push(to);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class IfcTemplatedEntityListList {
|
||||
std::vector< std::vector<T*> > ls;
|
||||
public:
|
||||
typedef typename boost::shared_ptr< IfcTemplatedEntityListList<T> > ptr;
|
||||
typedef typename std::vector< std::vector<T*> >::const_iterator outer_it;
|
||||
typedef typename std::vector<T*>::const_iterator inner_it;
|
||||
void push(const std::vector<T*>& t) {ls.push_back(t);}
|
||||
outer_it begin() { return ls.begin(); }
|
||||
outer_it end() { return ls.end(); }
|
||||
int size() const { return (int)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;
|
||||
if (std::find(inner.begin(), inner.end(), t) != inner.end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
IfcEntityListList::ptr generalize() {
|
||||
IfcEntityListList::ptr r (new IfcEntityListList());
|
||||
for (outer_it outer = begin(); outer != end(); ++ outer) {
|
||||
const std::vector<T*>& from = *outer;
|
||||
std::vector<IfcUtil::IfcBaseClass*> to;
|
||||
for (inner_it inner = from.begin(); inner != from.end(); ++ inner) {
|
||||
to.push_back(*inner);
|
||||
}
|
||||
r->push(to);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
namespace IfcParse {
|
||||
class IfcFile;
|
||||
}
|
||||
|
||||
class IFC_PARSE_API Argument {
|
||||
public:
|
||||
virtual operator int() const;
|
||||
virtual operator bool() const;
|
||||
virtual operator double() const;
|
||||
virtual operator std::string() const;
|
||||
virtual operator boost::dynamic_bitset<>() const;
|
||||
virtual operator IfcUtil::IfcBaseClass*() const;
|
||||
|
||||
virtual operator std::vector<int>() const;
|
||||
virtual operator std::vector<double>() const;
|
||||
virtual operator std::vector<std::string>() const;
|
||||
virtual operator std::vector<boost::dynamic_bitset<> >() const;
|
||||
virtual operator IfcEntityList::ptr() const;
|
||||
|
||||
virtual operator std::vector< std::vector<int> >() const;
|
||||
virtual operator std::vector< std::vector<double> >() const;
|
||||
virtual operator IfcEntityListList::ptr() const;
|
||||
|
||||
virtual bool isNull() const = 0;
|
||||
virtual unsigned int size() const = 0;
|
||||
|
||||
virtual IfcUtil::ArgumentType type() const = 0;
|
||||
virtual Argument* operator [] (unsigned int i) const = 0;
|
||||
virtual std::string toString(bool upper=false) const = 0;
|
||||
|
||||
virtual ~Argument() {};
|
||||
};
|
||||
|
||||
class IFC_PARSE_API IfcAbstractEntity {
|
||||
public:
|
||||
IfcParse::IfcFile* file;
|
||||
virtual IfcEntityList::ptr getInverse(IfcSchema::Type::Enum type, int attribute_index) = 0;
|
||||
virtual std::string datatype() const = 0;
|
||||
virtual Argument* getArgument (unsigned int i) = 0;
|
||||
virtual unsigned int getArgumentCount() const = 0;
|
||||
virtual ~IfcAbstractEntity() {};
|
||||
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 IfcWrite::IfcWritableEntity* isWritable() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,94 +0,0 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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 <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This namespace provides implementations of Argument and Entity that use STL *
|
||||
* containers for their datatypes and are not just lazy references to the *
|
||||
* IFC-SPF file. Therefore they can be modified by the client application. *
|
||||
* *
|
||||
* An IfcWritableEntity can be constructed from a regular IfcParse entity to be *
|
||||
* able to modify the data in existing IFC files. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCWRITABLEENTITY_H
|
||||
#define IFCWRITABLEENTITY_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <boost/dynamic_bitset.hpp>
|
||||
|
||||
#include "ifc_parse_api.h"
|
||||
|
||||
#include "IfcUtil.h"
|
||||
|
||||
namespace IfcWrite {
|
||||
class IFC_PARSE_API IfcWritableEntity : public IfcAbstractEntity {
|
||||
private:
|
||||
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);
|
||||
~IfcWritableEntity();
|
||||
|
||||
int setId(int i=-1);
|
||||
IfcWritableEntity(IfcAbstractEntity* e);
|
||||
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 v) const;
|
||||
std::string toString(bool upper=false) const;
|
||||
unsigned int id();
|
||||
IfcWritableEntity* isWritable();
|
||||
|
||||
void setArgument(int i, Argument* a, IfcUtil::ArgumentType attr_type = IfcUtil::Argument_UNKNOWN);
|
||||
|
||||
void setArgument(int i);
|
||||
void setArgumentDerived(int i);
|
||||
|
||||
void setArgument(int i,int v);
|
||||
void setArgument(int i,bool v);
|
||||
void setArgument(int i,double v);
|
||||
void setArgument(int i,const std::string& v);
|
||||
void setArgument(int i,const boost::dynamic_bitset<>& v);
|
||||
void setArgument(int i,int v, const char* c);
|
||||
void setArgument(int i,IfcUtil::IfcBaseClass* v);
|
||||
|
||||
void setArgument(int i,const std::vector<int>& v);
|
||||
void setArgument(int i,const std::vector<double>& v);
|
||||
void setArgument(int i,const std::vector<std::string>& v);
|
||||
void setArgument(int i,const std::vector< boost::dynamic_bitset<> >& v);
|
||||
void setArgument(int i,IfcEntityList::ptr v);
|
||||
|
||||
void setArgument(int i,const std::vector< std::vector<int> >& v);
|
||||
void setArgument(int i,const std::vector< std::vector<double> >& v);
|
||||
void setArgument(int i,IfcEntityListList::ptr v);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+26
-284
@@ -25,7 +25,6 @@
|
||||
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
#include "../ifcparse/IfcWrite.h"
|
||||
#include "../ifcparse/IfcWritableEntity.h"
|
||||
#include "../ifcparse/IfcCharacterDecoder.h"
|
||||
#include "../ifcparse/IfcFile.h"
|
||||
|
||||
@@ -37,268 +36,6 @@
|
||||
|
||||
using namespace IfcWrite;
|
||||
|
||||
IfcWritableEntity::IfcWritableEntity(IfcSchema::Type::Enum t) {
|
||||
_type = t;
|
||||
_id = 0;
|
||||
file = 0;
|
||||
}
|
||||
IfcWritableEntity::~IfcWritableEntity() {
|
||||
delete _id;
|
||||
for (std::map<int,Argument*>::iterator it = args.begin(); it != args.end(); ++it)
|
||||
delete it->second;
|
||||
}
|
||||
int IfcWritableEntity::setId(int i) {
|
||||
if (i > 0) {
|
||||
delete _id;
|
||||
return *(_id = new int(i));
|
||||
} else {
|
||||
if (_id) { return *_id; }
|
||||
else {
|
||||
delete _id;
|
||||
return *(_id = new int(file->FreshId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
IfcWritableEntity::IfcWritableEntity(IfcAbstractEntity* e)
|
||||
{
|
||||
file = e->file;
|
||||
_type = e->type();
|
||||
_id = new int(e->id());
|
||||
|
||||
const unsigned int count = e->getArgumentCount();
|
||||
for ( unsigned int i = 0; i < count; ++ i ) {
|
||||
this->setArgument(i, e->getArgument(i));
|
||||
}
|
||||
}
|
||||
|
||||
IfcEntityList::ptr IfcWritableEntity::getInverse(IfcSchema::Type::Enum type, int attribute_index) {
|
||||
if (file) {
|
||||
int id = _id ? *_id : setId();
|
||||
return file->getInverse(id, type, attribute_index);
|
||||
} else {
|
||||
throw IfcParse::IfcException("Instance not part of a file");
|
||||
}
|
||||
}
|
||||
|
||||
std::string IfcWritableEntity::datatype() const { return IfcSchema::Type::ToString(_type); }
|
||||
Argument* IfcWritableEntity::getArgument (unsigned int i) {
|
||||
if (args[i] == 0) {
|
||||
_setArgument(i, boost::blank());
|
||||
}
|
||||
return args[i];
|
||||
}
|
||||
unsigned int IfcWritableEntity::getArgumentCount() const { return (unsigned)args.size(); }
|
||||
IfcSchema::Type::Enum IfcWritableEntity::type() const { return _type; }
|
||||
bool IfcWritableEntity::is(IfcSchema::Type::Enum v) const { return _type == v; }
|
||||
std::string IfcWritableEntity::toString(bool upper) const {
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
|
||||
std::string dt = datatype();
|
||||
if (upper) {
|
||||
boost::to_upper(dt);
|
||||
}
|
||||
|
||||
if (_id && !IfcSchema::Type::IsSimple(type())) {
|
||||
ss << "#" << *_id;
|
||||
ss << "=";
|
||||
}
|
||||
|
||||
ss << dt << "(";
|
||||
for (std::map<int,Argument*>::const_iterator it = args.begin(); it != args.end(); ++ it) {
|
||||
if ( it != args.begin() ) ss << ",";
|
||||
ss << it->second->toString(upper);
|
||||
}
|
||||
ss << ")";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
unsigned int IfcWritableEntity::id() {
|
||||
if (!file) {
|
||||
return 0;
|
||||
}
|
||||
if ( !_id ) {
|
||||
_id = new int(file->FreshId());
|
||||
}
|
||||
return *_id;
|
||||
}
|
||||
IfcWritableEntity* IfcWritableEntity::isWritable() { return this; }
|
||||
bool IfcWritableEntity::arg_writable(int i) {
|
||||
std::map<int,bool>::const_iterator it = writemask.find(i);
|
||||
if ( it == writemask.end() ) return false;
|
||||
else return it->second;
|
||||
}
|
||||
void IfcWritableEntity::arg_writable(int i, bool b) {
|
||||
writemask[i] = b;
|
||||
}
|
||||
|
||||
template <typename T> void IfcWritableEntity::_setArgument(int i, const T& t) {
|
||||
if ( arg_writable(i) ) delete args[i];
|
||||
IfcWriteArgument* arg = new IfcWriteArgument;
|
||||
args[i] = arg;
|
||||
arg->set(t);
|
||||
arg_writable(i,true);
|
||||
}
|
||||
|
||||
void IfcWritableEntity::setArgument(int i) {
|
||||
_setArgument(i, boost::none);
|
||||
}
|
||||
|
||||
void IfcWritableEntity::setArgument(int i, Argument* a, IfcUtil::ArgumentType attr_type) {
|
||||
if (attr_type == IfcUtil::Argument_UNKNOWN) {
|
||||
attr_type = a->type();
|
||||
}
|
||||
switch(attr_type) {
|
||||
case IfcUtil::Argument_NULL:
|
||||
this->setArgument(i);
|
||||
break;
|
||||
case IfcUtil::Argument_DERIVED:
|
||||
this->setArgumentDerived(i);
|
||||
break;
|
||||
case IfcUtil::Argument_INT:
|
||||
this->setArgument(i, static_cast<int>(*a));
|
||||
break;
|
||||
case IfcUtil::Argument_BOOL:
|
||||
this->setArgument(i, static_cast<bool>(*a));
|
||||
break;
|
||||
case IfcUtil::Argument_DOUBLE:
|
||||
this->setArgument(i, static_cast<double>(*a));
|
||||
break;
|
||||
case IfcUtil::Argument_STRING:
|
||||
this->setArgument(i, static_cast<std::string>(*a));
|
||||
break;
|
||||
case IfcUtil::Argument_BINARY: {
|
||||
boost::dynamic_bitset<> attr_value = *a;
|
||||
this->setArgument(i, attr_value); }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_INT: {
|
||||
std::vector<int> attr_value = *a;
|
||||
this->setArgument(i, attr_value); }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_DOUBLE: {
|
||||
std::vector<double> attr_value = *a;
|
||||
this->setArgument(i, attr_value); }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_STRING: {
|
||||
std::vector<std::string> attr_value = *a;
|
||||
this->setArgument(i, attr_value); }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_BINARY: {
|
||||
std::vector< boost::dynamic_bitset<> > attr_value = *a;
|
||||
this->setArgument(i, attr_value); }
|
||||
break;
|
||||
case IfcUtil::Argument_ENUMERATION: {
|
||||
IfcSchema::Type::Enum ty = IfcSchema::Type::GetAttributeEntity(_type, (unsigned char)i);
|
||||
std::string enum_literal = a->toString();
|
||||
// Remove leading and trailing '.'
|
||||
enum_literal = enum_literal.substr(1, enum_literal.size() - 2);
|
||||
std::pair<const char*, int> enum_ref = IfcSchema::Type::GetEnumerationIndex(ty, enum_literal);
|
||||
this->setArgument(i, enum_ref.second, enum_ref.first); }
|
||||
break;
|
||||
case IfcUtil::Argument_ENTITY_INSTANCE: {
|
||||
this->setArgument(i, static_cast<IfcUtil::IfcBaseClass*>(*a)); }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: {
|
||||
IfcEntityList::ptr instances = *a;
|
||||
IfcEntityList::ptr mapped_instances(new IfcEntityList);
|
||||
for (IfcEntityList::it it = instances->begin(); it != instances->end(); ++it) {
|
||||
mapped_instances->push(*it);
|
||||
}
|
||||
this->setArgument(i, mapped_instances); }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT: {
|
||||
std::vector< std::vector<int> > attr_value = *a;
|
||||
this->setArgument(i, attr_value); }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE: {
|
||||
std::vector< std::vector<double> > attr_value = *a;
|
||||
this->setArgument(i, attr_value); }
|
||||
break;
|
||||
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE: {
|
||||
IfcEntityListList::ptr instances = *a;
|
||||
IfcEntityListList::ptr mapped_instances(new IfcEntityListList);
|
||||
for (IfcEntityListList::outer_it it = instances->begin(); it != instances->end(); ++it) {
|
||||
std::vector<IfcUtil::IfcBaseClass*> inner;
|
||||
for (IfcEntityListList::inner_it jt = it->begin(); jt != it->end(); ++jt) {
|
||||
inner.push_back(*jt);
|
||||
}
|
||||
mapped_instances->push(inner);
|
||||
}
|
||||
this->setArgument(i, mapped_instances); }
|
||||
break;
|
||||
case IfcUtil::Argument_EMPTY_AGGREGATE:
|
||||
case IfcUtil::Argument_AGGREGATE_OF_EMPTY_AGGREGATE: {
|
||||
IfcUtil::ArgumentType t2 = IfcSchema::Type::GetAttributeType(type(), (unsigned char) i);
|
||||
this->setArgument(i, a, t2); }
|
||||
break;
|
||||
default:
|
||||
case IfcUtil::Argument_UNKNOWN:
|
||||
throw IfcParse::IfcException(std::string("Unknown attribute encountered: '") + a->toString() + "' at index '" + boost::lexical_cast<std::string>(i) + "'");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void IfcWritableEntity::setArgumentDerived(int i) {
|
||||
_setArgument(i, IfcWriteArgument::Derived());
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,int v) {
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,bool v) {
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,int v, const char* c){
|
||||
_setArgument(i, IfcWriteArgument::EnumerationReference(v, c));
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::string& v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const boost::dynamic_bitset<>& v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,double v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,IfcUtil::IfcBaseClass* v){
|
||||
if ( v ) {
|
||||
_setArgument(i, v);
|
||||
} else {
|
||||
_setArgument(i, boost::none);
|
||||
}
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,IfcEntityList::ptr v){
|
||||
if ( v.get() ) {
|
||||
_setArgument(i, v);
|
||||
} else {
|
||||
_setArgument(i, boost::none);
|
||||
}
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,IfcEntityListList::ptr v){
|
||||
if ( v.get() ) {
|
||||
_setArgument(i, v);
|
||||
} else {
|
||||
_setArgument(i, boost::none);
|
||||
}
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::vector<double>& v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::vector< std::vector<double> >& v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::vector<std::string>& v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::vector<int>& v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::vector< std::vector<int> >& v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
void IfcWritableEntity::setArgument(int i,const std::vector< boost::dynamic_bitset<> >& v){
|
||||
_setArgument(i, v);
|
||||
}
|
||||
|
||||
class SizeVisitor : public boost::static_visitor<int> {
|
||||
public:
|
||||
int operator()(const boost::blank& /*i*/) const { return -1; }
|
||||
@@ -407,7 +144,7 @@ public:
|
||||
data << "." << i.enumeration_value << ".";
|
||||
}
|
||||
void operator()(const IfcUtil::IfcBaseClass* const& i) {
|
||||
IfcAbstractEntity* e = i->entity;
|
||||
IfcEntityInstanceData* e = i->entity;
|
||||
if ( IfcSchema::Type::IsSimple(e->type()) ) {
|
||||
data << e->toString(upper);
|
||||
} else {
|
||||
@@ -447,12 +184,8 @@ void StringBuilderVisitor::serialize(const std::vector<std::string>& i) {
|
||||
data << "(";
|
||||
for (std::vector<std::string>::const_iterator it = i.begin(); it != i.end(); ++it) {
|
||||
if (it != i.begin()) data << ",";
|
||||
if (upper) {
|
||||
std::string s = IfcCharacterEncoder(*it);
|
||||
data << s;
|
||||
} else {
|
||||
data << *it;
|
||||
}
|
||||
std::string s = IfcCharacterEncoder(*it);
|
||||
data << s;
|
||||
}
|
||||
data << ")";
|
||||
}
|
||||
@@ -540,20 +273,29 @@ IfcUtil::ArgumentType IfcWriteArgument::type() const {
|
||||
return static_cast<IfcUtil::ArgumentType>(container.which());
|
||||
}
|
||||
|
||||
EntityBuffer* EntityBuffer::i = 0;
|
||||
EntityBuffer* EntityBuffer::instance() {
|
||||
if ( ! i ) {
|
||||
i = new EntityBuffer();
|
||||
i->buffer = IfcEntityList::ptr(new IfcEntityList);
|
||||
// Overload to detect null values
|
||||
void IfcWriteArgument::set(const IfcEntityList::ptr& v) {
|
||||
if (v) {
|
||||
container = v;
|
||||
} else {
|
||||
container = boost::blank();
|
||||
}
|
||||
return i;
|
||||
}
|
||||
IfcEntityList::ptr EntityBuffer::Get() {
|
||||
return instance()->buffer;
|
||||
}
|
||||
void EntityBuffer::Clear() {
|
||||
instance()->buffer = IfcEntityList::ptr(new IfcEntityList);
|
||||
}
|
||||
void EntityBuffer::Add(IfcUtil::IfcBaseClass* e) {
|
||||
instance()->buffer->push(e);
|
||||
|
||||
// Overload to detect null values
|
||||
void IfcWriteArgument::set(const IfcEntityListList::ptr& v) {
|
||||
if (v) {
|
||||
container = v;
|
||||
} else {
|
||||
container = boost::blank();
|
||||
}
|
||||
}
|
||||
|
||||
// Overload to detect null values
|
||||
void IfcWriteArgument::set(IfcUtil::IfcBaseClass*const& v) {
|
||||
if (v) {
|
||||
container = v;
|
||||
} else {
|
||||
container = boost::blank();
|
||||
}
|
||||
}
|
||||
+22
-16
@@ -32,9 +32,13 @@
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/dynamic_bitset.hpp>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
#include <boost/type_traits/remove_pointer.hpp>
|
||||
|
||||
#include "ifc_parse_api.h"
|
||||
|
||||
#include "../ifcparse/IfcUtil.h"
|
||||
#include "../ifcparse/IfcBaseClass.h"
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
|
||||
namespace IfcWrite {
|
||||
@@ -111,17 +115,31 @@ namespace IfcWrite {
|
||||
IfcEntityListList::ptr
|
||||
> container;
|
||||
public:
|
||||
template <typename T> const T& as() const {
|
||||
|
||||
template <typename T>
|
||||
const T& as() const {
|
||||
if (const T* val = boost::get<T>(&container)) {
|
||||
return *val;
|
||||
} else {
|
||||
throw IfcParse::IfcException("Invalid cast");
|
||||
}
|
||||
}
|
||||
template <typename T> void set(const T& t) {
|
||||
|
||||
template <typename T>
|
||||
typename boost::disable_if<boost::is_base_of<IfcUtil::IfcBaseClass, typename boost::remove_pointer<T>::type>, void>::type
|
||||
set(const T& t) {
|
||||
container = t;
|
||||
}
|
||||
|
||||
// Overload to detect null values
|
||||
void set(const IfcEntityList::ptr& v);
|
||||
|
||||
// Overload to detect null values
|
||||
void set(const IfcEntityListList::ptr& v);
|
||||
|
||||
// Overload to detect null values
|
||||
void set(IfcUtil::IfcBaseClass*const & v);
|
||||
|
||||
operator int() const;
|
||||
operator bool() const;
|
||||
operator double() const;
|
||||
@@ -146,19 +164,7 @@ namespace IfcWrite {
|
||||
IfcUtil::ArgumentType type() const;
|
||||
};
|
||||
|
||||
// Accumulates all schema instances created from constructors
|
||||
// This way they can be added in a single batch to the IfcFile
|
||||
class IFC_PARSE_API EntityBuffer {
|
||||
private:
|
||||
IfcEntityList::ptr buffer;
|
||||
static EntityBuffer* i;
|
||||
static EntityBuffer* instance();
|
||||
public:
|
||||
static IfcEntityList::ptr Get();
|
||||
static void Clear();
|
||||
static void Add(IfcUtil::IfcBaseClass* e);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user