+ add first prototype version of the IFC-STEP loader. Loads many test models fine but does not support some of the more sophisticated format features.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@979 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2011-05-06 23:55:38 +00:00
parent a83183d95f
commit 1400ae79e7
19 changed files with 12451 additions and 8 deletions

View File

@ -314,6 +314,16 @@ SOURCE_GROUP(BLENDER FILES
BlenderModifier.cpp
)
SOURCE_GROUP(IFC FILES
IFCLoader.cpp
IFCLoader.h
IFCReaderGen.cpp
IFCReaderGen.h
STEPFile.h
STEPFileReader.h
STEPFileReader.cpp
)
SOURCE_GROUP( PostProcessing FILES
CalcTangentsProcess.cpp
CalcTangentsProcess.h
@ -742,6 +752,13 @@ ADD_LIBRARY( assimp SHARED
DeboneProcess.h
ColladaExporter.h
ColladaExporter.cpp
IFCLoader.cpp
IFCLoader.h
IFCReaderGen.cpp
IFCReaderGen.h
STEPFile.h
STEPFileReader.h
STEPFileReader.cpp
# Necessary to show the headers in the project when using the VC++ generator:
BoostWorkaround/boost/math/common_factor_rt.hpp

1270
code/IFCLoader.cpp 100644

File diff suppressed because it is too large Load Diff

141
code/IFCLoader.h 100644
View File

@ -0,0 +1,141 @@
/*
Open Asset Import Library (ASSIMP)
----------------------------------------------------------------------
Copyright (c) 2006-2010, ASSIMP Development Team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the ASSIMP Development Team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file IFC.h
* @brief Declaration of the Industry Foundation Classes (IFC) loader main class
*/
#ifndef INCLUDED_AI_IFC_LOADER_H
#define INCLUDED_AI_IFC_LOADER_H
#include "BaseImporter.h"
namespace Assimp {
// TinyFormatter.h
namespace Formatter {
template <typename T,typename TR, typename A> class basic_formatter;
typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
}
namespace STEP {
class DB;
}
// -------------------------------------------------------------------------------------------
/** Load the IFC format, which is an open specification to describe building and construction
industry data.
See http://en.wikipedia.org/wiki/Industry_Foundation_Classes
*/
// -------------------------------------------------------------------------------------------
class IFCImporter : public BaseImporter
{
friend class Importer;
protected:
/** Constructor to be privately used by Importer */
IFCImporter();
/** Destructor, private as well */
~IFCImporter();
public:
// --------------------
bool CanRead( const std::string& pFile,
IOSystem* pIOHandler,
bool checkSig
) const;
protected:
// --------------------
void GetExtensionList(std::set<std::string>& app);
// --------------------
void SetupProperties(const Importer* pImp);
// --------------------
void InternReadFile( const std::string& pFile,
aiScene* pScene,
IOSystem* pIOHandler
);
private:
public:
// loader settings, publicy accessible via their corresponding AI_CONFIG constants
struct Settings
{
Settings()
: skipSpaceRepresentations()
, skipCurveRepresentations()
{}
bool skipSpaceRepresentations;
bool skipCurveRepresentations;
};
public:
// -------------------------------------------------------------------
/** Prepend 'IFC: ' and throw msg.*/
static void ThrowException(const std::string& msg);
// -------------------------------------------------------------------
/** @defgroup blog Prepend 'IFC: ' and write @c message to log.*/
static void LogWarn (const Formatter::format& message); //! @ingroup blog
static void LogError (const Formatter::format& message); //! @ingroup blog
static void LogInfo (const Formatter::format& message); //! @ingroup blog
static void LogDebug (const Formatter::format& message); //! @ingroup blog
private:
Settings settings;
}; // !class IFCImporter
} // end of namespace Assimp
#endif // !INCLUDED_AI_IFC_LOADER_H

4480
code/IFCReaderGen.cpp 100644

File diff suppressed because it is too large Load Diff

4210
code/IFCReaderGen.h 100644

File diff suppressed because it is too large Load Diff

View File

@ -54,8 +54,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* further imports with the same Importer instance could fail/crash/burn ...
*/
// ------------------------------------------------------------------------------------------------
#define ASSIMP_CATCH_GLOBAL_EXCEPTIONS
#ifndef ASSIMP_BUILD_DEBUG
# define ASSIMP_CATCH_GLOBAL_EXCEPTIONS
#endif
// ------------------------------------------------------------------------------------------------
// Internal headers
@ -184,6 +185,9 @@ using namespace Assimp::Formatter;
#ifndef ASSIMP_BUILD_NO_NDO_IMPORTER
# include "NDOLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
# include "IFCLoader.h"
#endif
// ------------------------------------------------------------------------------------------------
// Post processing-Steps
@ -432,6 +436,9 @@ Importer::Importer()
#if (!defined ASSIMP_BUILD_NO_NDO_IMPORTER)
pimpl->mImporter.push_back( new NDOImporter() );
#endif
#if (!defined ASSIMP_BUILD_NO_IFC_IMPORTER)
pimpl->mImporter.push_back( new IFCImporter() );
#endif
// ----------------------------------------------------------------------------
// Add an instance of each post processing step here in the order

View File

@ -189,7 +189,7 @@ public:
return &cur;
}
const std::string& operator* () const {
std::string operator* () const {
return cur;
}

View File

@ -48,21 +48,54 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StringComparison.h"
namespace Assimp {
// NOTE: the functions below are mostly intended as replacement for
// std::upper, std::lower, std::isupper, std::islower, std::isspace.
// we don't bother of locales. We don't want them. We want reliable
// (i.e. identical) results across all locales.
// The functions below accept any character type, but know only
// about ASCII. However, UTF-32 is the only safe ASCII superset to
// use since it doesn't have multibyte sequences.
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsSpace( const char_t in)
AI_FORCE_INLINE char_t ToLower( char_t in)
{
return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in+0x20) : in;
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE char_t ToUpper( char_t in)
{
return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in;
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsUpper( char_t in)
{
return (in >= (char_t)'A' && in <= (char_t)'Z');
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsLower( char_t in)
{
return (in >= (char_t)'a' && in <= (char_t)'z');
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsSpace( char_t in)
{
return (in == (char_t)' ' || in == (char_t)'\t');
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsLineEnd( const char_t in)
AI_FORCE_INLINE bool IsLineEnd( char_t in)
{
return (in == (char_t)'\r' || in == (char_t)'\n' || in == (char_t)'\0');
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsSpaceOrNewLine( const char_t in)
AI_FORCE_INLINE bool IsSpaceOrNewLine( char_t in)
{
return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
}

954
code/STEPFile.h 100644
View File

@ -0,0 +1,954 @@
/*
Open Asset Import Library (ASSIMP)
----------------------------------------------------------------------
Copyright (c) 2006-2010, ASSIMP Development Team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the ASSIMP Development Team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#ifndef INCLUDED_AI_STEPFILE_H
#define INCLUDED_AI_STEPFILE_H
#include <boost/noncopyable.hpp>
#include <bitset>
//
#if _MSC_VER >= 1500 || (defined __GNUC___)
# define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
# else
# define step_unordered_map map
# define step_unordered_multimap multimap
#endif
#ifdef ASSIMP_STEP_USE_UNORDERED_MULTIMAP
# include <unordered_map>
# if _MSC_VER > 1600
# define step_unordered_map unordered_map
# define step_unordered_multimap unordered_multimap
# else
# define step_unordered_map tr1::unordered_map
# define step_unordered_multimap tr1::unordered_multimap
# endif
#endif
#include "LineSplitter.h"
// uncomment this to have the loader evaluate all entities upon loading.
// this is intended as stress test - by default, entities are evaluated
// lazily and therefore not unless needed.
//#define ASSIMP_IFC_TEST
namespace Assimp {
// ********************************************************************************
// before things get complicated, this is the basic outline:
namespace STEP {
namespace EXPRESS {
// base data types known by EXPRESS schemata - any custom data types will derive one of those
class DataType;
class UNSET; /*: public DataType */
class ISDERIVED; /*: public DataType */
// class REAL; /*: public DataType */
class ENUM; /*: public DataType */
// class STRING; /*: public DataType */
// class INTEGER; /*: public DataType */
class ENTITY; /*: public DataType */
class LIST; /*: public DataType */
// class SELECT; /*: public DataType */
// a conversion schema is not exactly an EXPRESS schema, rather it
// is a list of pointers to conversion functions to build up the
// object tree from an input file.
class ConversionSchema;
}
struct HeaderInfo;
class Object;
class LazyObject;
class DB;
typedef Object* (*ConvertObjectProc)(const DB& db, const EXPRESS::LIST& params);
}
// ********************************************************************************
namespace STEP {
// -------------------------------------------------------------------------------
/** Exception class used by the STEP loading & parsing code. It is typically
* coupled with a line number. */
// -------------------------------------------------------------------------------
struct SyntaxError : DeadlyImportError
{
enum {
LINE_NOT_SPECIFIED = 0xffffffffffffffffLL
};
SyntaxError (const std::string& s,uint64_t line = LINE_NOT_SPECIFIED);
};
// -------------------------------------------------------------------------------
/** Exception class used by the STEP loading & parsing code when a type
* error (i.e. an entity expects a string but receives a bool) occurs.
* It is typically coupled with both an entity id and a line number.*/
// -------------------------------------------------------------------------------
struct TypeError : DeadlyImportError
{
enum {
ENTITY_NOT_SPECIFIED = 0xffffffffffffffffLL
};
TypeError (const std::string& s,uint64_t entity = ENTITY_NOT_SPECIFIED, uint64_t line = SyntaxError::LINE_NOT_SPECIFIED);
};
// hack to make a given member template-dependent
template <typename T, typename T2>
T2& Couple(T2& in) {
return in;
}
namespace EXPRESS {
// -------------------------------------------------------------------------------
//** Base class for all STEP data types */
// -------------------------------------------------------------------------------
class DataType
{
public:
typedef const DataType* Out;
public:
virtual ~DataType() {
}
public:
template <typename T>
const T& To() const {
return dynamic_cast<const T&>(*this);
}
template <typename T>
T& To() {
return dynamic_cast<T&>(*this);
}
template <typename T>
const T* ToPtr() const {
return dynamic_cast<const T*>(this);
}
template <typename T>
T* ToPtr() {
return dynamic_cast<T*>(this);
}
// utilities to deal with SELECT entities, which currently lack automatic
// conversion support.
template <typename T>
const T& ResolveSelect(const DB& db) const {
return Couple<T>(db).MustGetObject(To<EXPRESS::ENTITY>())->To<T>();
}
template <typename T>
const T* ResolveSelectPtr(const DB& db) const {
const EXPRESS::ENTITY* e = ToPtr<EXPRESS::ENTITY>();
return e?Couple<T>(db).MustGetObject(*e)->ToPtr<T>():(const T*)0;
}
public:
/** parse a variable from a string and set 'inout' to the character
* behind the last consumed character. An optional schema enables,
* if specified, automatic conversion of custom data types.
*
* @throw SyntaxError
*/
static const DataType* Parse(const char*& inout,
uint64_t line = SyntaxError::LINE_NOT_SPECIFIED,
const EXPRESS::ConversionSchema* schema = NULL);
public:
};
typedef DataType SELECT;
typedef DataType LOGICAL;
// -------------------------------------------------------------------------------
/** Sentinel class to represent explicitly unset (optional) fields ($) */
// -------------------------------------------------------------------------------
class UNSET : public DataType
{
public:
private:
};
// -------------------------------------------------------------------------------
/** Sentinel class to represent explicitly derived fields (*) */
// -------------------------------------------------------------------------------
class ISDERIVED : public DataType
{
public:
private:
};
// -------------------------------------------------------------------------------
/** Shared implementation for some of the primitive data type, i.e. int, float */
// -------------------------------------------------------------------------------
template <typename T>
class PrimitiveDataType : public DataType
{
public:
// This is the type that will ultimatively be used to
// expose this data type to the user.
typedef T Out;
public:
PrimitiveDataType() {}
PrimitiveDataType(const T& val)
: val(val)
{}
PrimitiveDataType(const PrimitiveDataType& o) {
(*this) = o;
}
public:
operator const T& () const {
return val;
}
PrimitiveDataType& operator=(const PrimitiveDataType& o) {
val = o.val;
return *this;
}
protected:
T val;
};
typedef PrimitiveDataType<int64_t> INTEGER;
typedef PrimitiveDataType<float> REAL;
typedef PrimitiveDataType<float> NUMBER;
typedef PrimitiveDataType<std::string> STRING;
// -------------------------------------------------------------------------------
/** Generic base class for all enumerated types */
// -------------------------------------------------------------------------------
class ENUMERATION : public STRING
{
public:
ENUMERATION (const std::string& val)
: STRING(val)
{}
private:
};
typedef ENUMERATION BOOLEAN;
// -------------------------------------------------------------------------------
/** This is just a reference to an entity/object somewhere else */
// -------------------------------------------------------------------------------
class ENTITY : public PrimitiveDataType<uint64_t>
{
public:
ENTITY(uint64_t val)
: PrimitiveDataType<uint64_t>(val)
{
ai_assert(val!=0);
}
ENTITY()
: PrimitiveDataType<uint64_t>(TypeError::ENTITY_NOT_SPECIFIED)
{
}
private:
};
// -------------------------------------------------------------------------------
/** Wrap any STEP aggregate: LIST, SET, ... */
// -------------------------------------------------------------------------------
class LIST : public DataType
{
public:
// access a particular list index, throw std::range_error for wrong indices
const DataType* operator[] (size_t index) const {
return members[index].get();
}
size_t GetSize() const {
return members.size();
}
public:
/** @see DaraType::Parse */
static const LIST* Parse(const char*& inout,
uint64_t line = SyntaxError::LINE_NOT_SPECIFIED,
const EXPRESS::ConversionSchema* schema = NULL);
private:
typedef std::vector< boost::shared_ptr<const DataType> > MemberList;
MemberList members;
};
// -------------------------------------------------------------------------------
/* Not exactly a full EXPRESS schema but rather a list of conversion functions
* to extract valid C++ objects out of a STEP file. Those conversion functions
* may, however, perform further schema validations. */
// -------------------------------------------------------------------------------
class ConversionSchema
{
public:
struct SchemaEntry {
SchemaEntry(const char* name,ConvertObjectProc func)
: name(name)
, func(func)
{}
const char* name;
ConvertObjectProc func;
};
public:
template <size_t N>
explicit ConversionSchema( const SchemaEntry (& schemas)[N]) {
*this = schemas;
}
ConversionSchema() {}
public:
ConvertObjectProc GetConverterProc(const std::string& name) const {
std::map<std::string,ConvertObjectProc>::const_iterator it = converters.find(name);
return it == converters.end() ? NULL : (*it).second;
}
bool IsKnownToken(const std::string& name) const {
return converters.find(name) != converters.end();
}
template <size_t N>
const ConversionSchema& operator=( const SchemaEntry (& schemas)[N]) {
for(size_t i = 0; i < N; ++i ) {
const SchemaEntry& schema = schemas[i];
converters[schema.name] = schema.func;
}
return *this;
}
private:
std::map<std::string,ConvertObjectProc> converters;
};
}
// ------------------------------------------------------------------------------
/** Bundle all the relevant info from a STEP header, parts of which may later
* be plainly dumped to the logfile, whereas others may help the caller pick an
* appropriate loading strategy.*/
// ------------------------------------------------------------------------------
struct HeaderInfo
{
std::string timestamp;
std::string app;
std::string fileSchema;
};
// ------------------------------------------------------------------------------
/** Base class for all concrete object instances */
// ------------------------------------------------------------------------------
class Object
{
public:
virtual ~Object() {}
public:
// utilities to simplify casting to concrete types
template <typename T>
const T& To() const {
return dynamic_cast<const T&>(*this);
}
template <typename T>
T& To() {
return dynamic_cast<T&>(*this);
}
template <typename T>
const T* ToPtr() const {
return dynamic_cast<const T*>(this);
}
template <typename T>
T* ToPtr() {
return dynamic_cast<T*>(this);
}
public:
uint64_t GetID() const {
return id;
}
std::string GetClassName() const {
// strictly speaking this relies on unspecified behaviour - we hijack the name() field of std::type_info
const char* s = typeid(*this).name(), *s2 = strstr(s,"IFC::");
return std::string(s2?s2+5:s);
}
void SetID(uint64_t newval) {
id = newval;
}
private:
uint64_t id;
};
template <typename T>
size_t GenericFill(const STEP::DB& db, const EXPRESS::LIST& params, T* in);
// (intentionally undefined)
// ------------------------------------------------------------------------------
/** CRTP shared base class for use by concrete entity implementation classes */
// ------------------------------------------------------------------------------
template <typename TDerived, size_t arg_count>
struct ObjectHelper : virtual Object
{
ObjectHelper() : aux_is_derived(0) {}
static Object* Construct(const STEP::DB& db, const EXPRESS::LIST& params) {
// make sure we don't leak if Fill() throws an exception
std::auto_ptr<TDerived> impl(new TDerived());
// GenericFill<T> is undefined so we need to have a specialization
const size_t num_args = GenericFill<TDerived>(db,params,&*impl);
// the following check is commented because it will always trigger if
// parts of the entities are generated with dummy wrapper code.
// This is currently done to reduce the size of the loader
// code.
//if (num_args != params.GetSize() && impl->GetClassName() != "NotImplemented") {
// DefaultLogger::get()->debug("STEP: not all parameters consumed");
//}
return impl.release();
}
// note that this member always exists multiple times within the hierarchy
// of an individual object, so any access to it must be disambiguated.
std::bitset<arg_count> aux_is_derived;
};
// ------------------------------------------------------------------------------
/** Class template used to represent OPTIONAL data members in the converted schema */
// ------------------------------------------------------------------------------
template <typename T>
struct Maybe
{
Maybe() : have() {}
explicit Maybe(const T& ptr) : ptr(ptr), have(true) {
}
void flag_invalid() {
have = false;
}
void flag_valid() {
have = true;
}
bool operator! () const {
return !have;
}
operator bool() const {
return have;
}
operator const T&() const {
return Get();
}
const T& Get() const {
ai_assert(have);
return ptr;
}
Maybe& operator=(const T& _ptr) {
ptr = _ptr;
have = true;
return *this;
}
private:
template <typename T2> friend struct InternGenericConvert;
operator T&() {
return ptr;
}
T ptr;
bool have;
};
// ------------------------------------------------------------------------------
/** A LazyObject is created when needed. Before this happens, we just keep
the text line that contains the object definition. */
// -------------------------------------------------------------------------------
class LazyObject : public boost::noncopyable
{
friend class DB;
public:
LazyObject(DB& db, uint64_t id,uint64_t line,const std::string& type,const std::string& args);
~LazyObject();
public:
Object& operator * () {
if (!obj) {
LazyInit();
ai_assert(obj);
}
return *obj;
}
const Object& operator * () const {
if (!obj) {
LazyInit();
ai_assert(obj);
}
return *obj;
}
template <typename T>
const T& To() const {
return dynamic_cast<const T&>( **this );
}
template <typename T>
T& To() {
return dynamic_cast<T&>( **this );
}
template <typename T>
const T* ToPtr() const {
return dynamic_cast<const T*>( &**this );
}
template <typename T>
T* ToPtr() {
return dynamic_cast<T*>( &**this );
}
Object* operator -> () {
return &**this;
}
const Object* operator -> () const {
return &**this;
}
bool operator== (const std::string& atype) const {
return type == atype;
}
bool operator!= (const std::string& atype) const {
return type != atype;
}
private:
void LazyInit() const;
private:
const uint64_t id, line;
const std::string type;
DB& db;
const EXPRESS::LIST* conv_args;
mutable Object* obj;
};
template <typename T>
inline bool operator==( boost::shared_ptr<LazyObject> lo, T whatever ) {
return *lo == whatever; // XXX use std::forward if we have 0x
}
template <typename T>
inline bool operator==( const std::pair<uint64_t, boost::shared_ptr<LazyObject> >& lo, T whatever ) {
return *(lo.second) == whatever; // XXX use std::forward if we have 0x
}
// ------------------------------------------------------------------------------
/** Class template used to represent lazily evaluated object references in the converted schema */
// ------------------------------------------------------------------------------
template <typename T>
struct Lazy
{
typedef Lazy Out;
Lazy(const LazyObject* obj = NULL) : obj(obj) {
}
operator const T&() const {
return obj->To<T>();
}
const T& operator * () const {
return obj->To<T>();
}
const T* operator -> () const {
return &obj->To<T>();
}
const LazyObject* obj;
};
// ------------------------------------------------------------------------------
/** Class template used to represent LIST and SET data members in the converted schema */
// ------------------------------------------------------------------------------
template <typename T, uint64_t min_cnt, uint64_t max_cnt=0uL>
struct ListOf : public std::vector<typename T::Out>
{
typedef typename T::Out OutScalar;
typedef ListOf Out;
BOOST_STATIC_ASSERT(min_cnt <= max_cnt || !max_cnt);
ListOf() {
}
};
// ------------------------------------------------------------------------------
template <typename TOut>
struct PickBaseType {
typedef EXPRESS::PrimitiveDataType<TOut> Type;
};
template <typename TOut>
struct PickBaseType< Lazy<TOut> > {
typedef EXPRESS::ENTITY Type;
};
template <> struct PickBaseType<EXPRESS::DataType*>;
// ------------------------------------------------------------------------------
template <typename T>
struct InternGenericConvert {
void operator()(T& out, const EXPRESS::DataType& in, const STEP::DB& db) {
try{
out = dynamic_cast< const typename PickBaseType<T>::Type& > ( in );
}
catch(std::bad_cast&) {
throw TypeError("type error reading literal field");
}
}
};
template <>
struct InternGenericConvert<const EXPRESS::DataType*> {
void operator()(const EXPRESS::DataType*& out, const EXPRESS::DataType& in, const STEP::DB& db) {
out = &in;
}
};
template <typename T>
struct InternGenericConvert< Maybe<T> > {
void operator()(Maybe<T>& out, const EXPRESS::DataType& in, const STEP::DB& db) {
GenericConvert((T&)out,in,db);
out.flag_valid();
}
};
template <typename T,uint64_t min_cnt, uint64_t max_cnt>
struct InternGenericConvertList {
void operator()(ListOf<T, min_cnt, max_cnt>& out, const EXPRESS::DataType& inp_base, const STEP::DB& db) {
const EXPRESS::LIST* inp = dynamic_cast<const EXPRESS::LIST*>(&inp_base);
if (!inp) {
throw TypeError("type error reading aggregate");
}
// XXX is this really how the EXPRESS notation ([?:3],[1:3]) .. works?
// too many is warning, too few is critical error because the user won't validate this
if (max_cnt && inp->GetSize() > max_cnt) {
DefaultLogger::get()->warn("too many aggregate elements");
}
else if (inp->GetSize() < min_cnt) {
throw TypeError("too few aggregate elements");
}
out.reserve(inp->GetSize());
for(size_t i = 0; i < inp->GetSize(); ++i) {
out.push_back( typename ListOf<T, min_cnt, max_cnt>::OutScalar() );
try{
GenericConvert(out.back(),*(*inp)[i], db);
}
catch(const TypeError& t) {
throw TypeError(t.what() +std::string(" of aggregate"));
}
}
}
};
template <typename T>
struct InternGenericConvert< Lazy<T> > {
void operator()(Lazy<T>& out, const EXPRESS::DataType& in_base, const STEP::DB& db) {
const EXPRESS::ENTITY* in = dynamic_cast<const EXPRESS::ENTITY*>(&in_base);
if (!in) {
throw TypeError("type error reading entity");
}
out = Couple<T>(db).GetObject(*in);
}
};
template <typename T1>
inline void GenericConvert(T1& a, const EXPRESS::DataType& b, const STEP::DB& db) {
return InternGenericConvert<T1>()(a,b,db);
}
template <typename T1,uint64_t N1, uint64_t N2>
inline void GenericConvert(ListOf<T1,N1,N2>& a, const EXPRESS::DataType& b, const STEP::DB& db) {
return InternGenericConvertList<T1,N1,N2>()(a,b,db);
}
// ------------------------------------------------------------------------------
/** Lightweight manager class that holds the map of all objects in a
* STEP file. DB's are exclusively maintained by the functions in
* STEPFileReader.h*/
// -------------------------------------------------------------------------------
class DB
{
friend DB* ReadFileHeader(boost::shared_ptr<IOStream> stream);
friend void ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme);
friend class LazyObject;
public:
// objects indexed by ID
typedef std::map<uint64_t,boost::shared_ptr<const LazyObject> > ObjectMap;
// objects indexed by their declarative type
typedef std::step_unordered_multimap<std::string, const LazyObject* > ObjectMapByType;
typedef std::pair<ObjectMapByType::const_iterator,ObjectMapByType::const_iterator> ObjectMapRange;
// references - for each object id the ids of all objects which reference it
typedef std::multimap<uint64_t, uint64_t > RefMap;
typedef std::pair<RefMap::const_iterator,RefMap::const_iterator> RefMapRange;
private:
DB(boost::shared_ptr<StreamReaderLE> reader)
: reader(reader)
, splitter(*reader,true,true)
, evaluated_count()
{}
public:
uint64_t GetObjectCount() const {
return objects.size();
}
uint64_t GetEvaluatedObjectCount() const {
return evaluated_count;
}
const HeaderInfo& GetHeader() const {
return header;
}
const EXPRESS::ConversionSchema& GetSchema() const {
return *schema;
}
const ObjectMap& GetObjects() const {
return objects;
}
const ObjectMapByType& GetObjectsByType() const {
return objects_bytype;
}
const RefMap& GetRefs() const {
return refs;
}
// get the yet unevaluated object record with a given id
const LazyObject* GetObject(uint64_t id) const {
const ObjectMap::const_iterator it = objects.find(id);
if (it != objects.end()) {
return (*it).second.get();
}
return NULL;
}
// get an arbitrary object out of the soup with the only restriction being its type.
const LazyObject* GetObject(const std::string& type) const {
const ObjectMapByType::const_iterator it = objects_bytype.find(type);
if (it != objects_bytype.end()) {
return (*it).second;
}
return NULL;
}
// same, but raise an exception if the object doesn't exist and return a reference
const LazyObject& MustGetObject(uint64_t id) const {
const LazyObject* o = GetObject(id);
if (!o) {
throw TypeError("requested entity is not present",id);
}
return *o;
}
const LazyObject& MustGetObject(const std::string& type) const {
const LazyObject* o = GetObject(type);
if (!o) {
throw TypeError("requested entity of type "+type+"is not present");
}
return *o;
}
#ifdef ASSIMP_IFC_TEST
// evaluate *all* entities in the file. this is a power test for the loader
void EvaluateAll() {
BOOST_FOREACH(ObjectMap::value_type& e,objects) {
**e.second;
}
ai_assert(evaluated_count == objects.size());
}
#endif
private:
// full access only offered to close friends - they should
// use the provided getters rather than messing around with
// the members directly.
LineSplitter& GetSplitter() {
return splitter;
}
void InternInsert(boost::shared_ptr<LazyObject> lz) {
objects[lz->id] = lz;
objects_bytype.insert(std::make_pair(lz->type,lz.get()));
}
void SetSchema(const EXPRESS::ConversionSchema& _schema) {
schema = &_schema;
}
HeaderInfo& GetHeader() {
return header;
}
void MarkRef(uint64_t who, uint64_t by_whom) {
refs.insert(std::make_pair(who,by_whom));
}
private:
HeaderInfo header;
ObjectMap objects;
ObjectMapByType objects_bytype;
RefMap refs;
boost::shared_ptr<StreamReaderLE> reader;
LineSplitter splitter;
uint64_t evaluated_count;
const EXPRESS::ConversionSchema* schema;
};
}
} // end Assimp
#endif

View File

@ -0,0 +1,445 @@
/*
Open Asset Import Library (ASSIMP)
----------------------------------------------------------------------
Copyright (c) 2006-2010, ASSIMP Development Team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the ASSIMP Development Team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file STEPFileReader.cpp
* @brief Implementation of the STEP file parser, which fills a
* STEP::DB with data read from a file.
*/
#include "AssimpPCH.h"
#include "STEPFileReader.h"
#include "TinyFormatter.h"
#include "fast_atof.h"
using namespace Assimp;
namespace EXPRESS = STEP::EXPRESS;
#include <functional>
// ------------------------------------------------------------------------------------------------
// From http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
// trim from start
static inline std::string &ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1( std::ptr_fun(Assimp::IsSpace<char>))));
return s;
}
// trim from end
static inline std::string &rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1( std::ptr_fun(Assimp::IsSpace<char>))).base());
return s;
}
// trim from both ends
static inline std::string &trim(std::string &s) {
return ltrim(rtrim(s));
}
// ------------------------------------------------------------------------------------------------
std::string AddLineNumber(const std::string& s,uint64_t line /*= LINE_NOT_SPECIFIED*/, const std::string& prefix = "")
{
return line == STEP::SyntaxError::LINE_NOT_SPECIFIED ? prefix+s : static_cast<std::string>( (Formatter::format(),prefix,"(line ",line,") ",s) );
}
// ------------------------------------------------------------------------------------------------
std::string AddEntityID(const std::string& s,uint64_t entity /*= ENTITY_NOT_SPECIFIED*/, const std::string& prefix = "")
{
return entity == STEP::TypeError::ENTITY_NOT_SPECIFIED ? prefix+s : static_cast<std::string>( (Formatter::format(),prefix,"(entity #",entity,") ",s));
}
// ------------------------------------------------------------------------------------------------
STEP::SyntaxError::SyntaxError (const std::string& s,uint64_t line /* = LINE_NOT_SPECIFIED */)
: DeadlyImportError(AddLineNumber(s,line))
{
}
// ------------------------------------------------------------------------------------------------
STEP::TypeError::TypeError (const std::string& s,uint64_t entity /* = ENTITY_NOT_SPECIFIED */,uint64_t line /*= LINE_NOT_SPECIFIED*/)
: DeadlyImportError(AddLineNumber(AddEntityID(s,entity),line))
{
}
// ------------------------------------------------------------------------------------------------
STEP::DB* STEP::ReadFileHeader(boost::shared_ptr<IOStream> stream)
{
boost::shared_ptr<StreamReaderLE> reader = boost::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream));
std::auto_ptr<STEP::DB> db = std::auto_ptr<STEP::DB>(new STEP::DB(reader));
LineSplitter& splitter = db->GetSplitter();
if (!splitter || *splitter != "ISO-10303-21;") {
throw STEP::SyntaxError("expected magic token: ISO-10303-21",1);
}
HeaderInfo& head = db->GetHeader();
for(++splitter; splitter; ++splitter) {
const std::string& s = *splitter;
if (s == "DATA;") {
// here we go, header done, start of data section
++splitter;
break;
}
// want one-based line numbers for human readers, so +1
const uint64_t line = splitter.get_index()+1;
if (s.substr(0,11) == "FILE_SCHEMA") {
const char* sz = s.c_str()+11;
SkipSpaces(sz,&sz);
std::auto_ptr< const EXPRESS::DataType > schema = std::auto_ptr< const EXPRESS::DataType >( EXPRESS::DataType::Parse(sz) );
// the file schema should be a regular list entity, although it usually contains exactly one entry
// since the list itself is contained in a regular parameter list, we actually have
// two nested lists.
const EXPRESS::LIST* list = dynamic_cast<const EXPRESS::LIST*>(schema.get());
if (list && list->GetSize()) {
list = dynamic_cast<const EXPRESS::LIST*>( (*list)[0] );
if (!list) {
throw STEP::SyntaxError("expected FILE_SCHEMA to be a list",line);
}
// XXX need support for multiple schemas?
if (list->GetSize() > 1) {
DefaultLogger::get()->warn(AddLineNumber("multiple schemas currently not supported",line));
}
const EXPRESS::STRING* string;
if (!list->GetSize() || !(string=dynamic_cast<const EXPRESS::STRING*>( (*list)[0] ))) {
throw STEP::SyntaxError("expected FILE_SCHEMA to contain a single string literal",line);
}
head.fileSchema = *string;
}
}
// XXX handle more header fields
}
return db.release();
}
// ------------------------------------------------------------------------------------------------
void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme)
{
db.SetSchema(scheme);
const DB::ObjectMap& map = db.GetObjects();
LineSplitter& splitter = db.GetSplitter();
for(; splitter; ++splitter) {
const std::string& s = *splitter;
if (s == "ENDSEC;") {
break;
}
// want one-based line numbers for human readers, so +1
const uint64_t line = splitter.get_index()+1;
// LineSplitter already ignores empty lines
ai_assert(s.length());
if (s[0] != '#') {
DefaultLogger::get()->warn(AddLineNumber("expected token \'#\'",line));
continue;
}
// ---
// extract id, entity class name and argument string,
// but don't create the actual object yet.
// ---
const std::string::size_type n0 = s.find_first_of('=');
if (n0 == std::string::npos) {
DefaultLogger::get()->warn(AddLineNumber("expected token \'=\'",line));
continue;
}
const uint64_t id = strtoul10_64(s.substr(1,n0-1).c_str());
if (!id) {
DefaultLogger::get()->warn(AddLineNumber("expected positive, numeric entity id",line));
continue;
}
const std::string::size_type n1 = s.find_first_of('(',n0);
if (n1 == std::string::npos) {
DefaultLogger::get()->warn(AddLineNumber("expected token \'(\'",line));
continue;
}
const std::string::size_type n2 = s.find_last_of(')');
if (n2 == std::string::npos || n2 < n1) {
DefaultLogger::get()->warn(AddLineNumber("expected token \')\'",line));
continue;
}
if (map.find(id) != map.end()) {
DefaultLogger::get()->warn(AddLineNumber((Formatter::format(),"an object with the id #",id," already exists"),line));
}
std::string type = s.substr(n0+1,n1-n0-1);
trim(type);
std::transform( type.begin(), type.end(), type.begin(), &Assimp::ToLower<char> );
db.InternInsert(boost::shared_ptr<LazyObject>(new LazyObject(db,id,line,type,s.substr(n1,n2-n1+1))));
}
if (!splitter) {
DefaultLogger::get()->warn("STEP: ignoring unexpected EOF");
}
if ( !DefaultLogger::isNullLogger() ){
DefaultLogger::get()->debug((Formatter::format(),"STEP: got ",map.size()," object records"));
}
}
// ------------------------------------------------------------------------------------------------
const EXPRESS::DataType* EXPRESS::DataType::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= NULL*/)
{
const char* cur = inout;
SkipSpaces(&cur);
if (*cur == ',' || IsSpaceOrNewLine(*cur)) {
throw STEP::SyntaxError("unexpected token, expected parameter",line);
}
// just skip over constructions such as IFCPLANEANGLEMEASURE(0.01) and read only the value
if (schema) {
bool ok = false;
for(const char* t = cur; *t && *t != ')' && *t != ','; ++t) {
if (*t=='(') {
if (!ok) {
break;
}
for(--t;IsSpace(*t);--t);
std::string s(cur,static_cast<size_t>(t-cur+1));
std::transform(s.begin(),s.end(),s.begin(),&ToLower<char> );
if (schema->IsKnownToken(s)) {
for(cur = t+1;*cur++ != '(';);
const EXPRESS::DataType* const dt = Parse(cur);
inout = *cur ? cur+1 : cur;
return dt;
}
break;
}
else if (!IsSpace(*t)) {
ok = true;
}
}
}
if (*cur == '*' ) {
inout = cur+1;
return new EXPRESS::ISDERIVED();
}
else if (*cur == '$' ) {
inout = cur+1;
return new EXPRESS::UNSET();
}
else if (*cur == '(' ) {
// start of an aggregate, further parsing is done by the LIST factory constructor
inout = cur;
return EXPRESS::LIST::Parse(inout,line,schema);
}
else if (*cur == '.' ) {
// enum (includes boolean)
const char* start = ++cur;
for(;*cur != '.';++cur) {
if (*cur == '\0') {
throw STEP::SyntaxError("enum not closed",line);
}
}
inout = cur+1;
return new EXPRESS::ENUMERATION( std::string(start, static_cast<size_t>(cur-start) ));
}
else if (*cur == '#' ) {
// object reference
return new EXPRESS::ENTITY(strtoul10_64(++cur,&inout));
}
else if (*cur == '\'' ) {
// string literal
const char* start = ++cur;
for(;*cur != '\'';++cur) {
if (*cur == '\0') {
throw STEP::SyntaxError("string literal not closed",line);
}
}
if (cur[1]=='\'') {
for(cur+=2;*cur != '\'';++cur) {
if (*cur == '\0') {
throw STEP::SyntaxError("string literal not closed",line);
}
}
}
inout = cur+1;
return new EXPRESS::STRING( std::string(start, static_cast<size_t>(cur-start) ));
}
else if (*cur == '\"' ) {
throw STEP::SyntaxError("binary data not supported yet",line);
}
// else -- must be a number. if there is a decimal dot in it,
// parse it as real value, otherwise as integer.
const char* start = cur;
for(;*cur && *cur != ',' && *cur != ')' && !IsSpace(*cur);++cur) {
if (*cur == '.') {
// XXX many STEP files contain extremely accurate data, float's precision may not suffice in many cases
float f;
inout = fast_atof_move(start,f);
return new EXPRESS::REAL(f);
}
}
bool neg = false;
if (*start == '-') {
neg = true;
++start;
}
else if (*start == '+') {
++start;
}
int64_t num = static_cast<int64_t>( strtoul10_64(start,&inout) );
return new EXPRESS::INTEGER(neg?-num:num);
}
// ------------------------------------------------------------------------------------------------
const EXPRESS::LIST* EXPRESS::LIST::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= NULL*/)
{
std::auto_ptr<EXPRESS::LIST> list(new EXPRESS::LIST());
EXPRESS::LIST::MemberList& members = list->members;
const char* cur = inout;
if (*cur++ != '(') {
throw STEP::SyntaxError("unexpected token, expected \'(\' token at beginning of list",line);
}
// estimate the number of items upfront - lists can grow large
size_t count = 1;
for(const char* c=cur; *c && *c != ')'; ++c) {
count += (*c == ',' ? 1 : 0);
}
members.reserve(count);
for(;;++cur) {
if (!*cur) {
throw STEP::SyntaxError("unexpected end of line while reading list");
}
SkipSpaces(cur,&cur);
if (*cur == ')') {
break;
}
members.push_back( boost::shared_ptr<const EXPRESS::DataType>(EXPRESS::DataType::Parse(cur,line,schema)));
SkipSpaces(cur,&cur);
if (*cur != ',') {
if (*cur == ')') {
break;
}
throw STEP::SyntaxError("unexpected token, expected \',\' or \')\' token after list element",line);
}
}
inout = cur+1;
return list.release();
}
// ------------------------------------------------------------------------------------------------
STEP::LazyObject::LazyObject(DB& db, uint64_t id,uint64_t line,const std::string& type,const std::string& args)
: db(db)
, id(id)
, line(line)
, type(type)
, obj()
// need to initialize this upfront, otherwise the destructor
// will crash if an exception is thrown in the c'tor
, conv_args()
{
const char* arg = args.c_str();
conv_args = EXPRESS::LIST::Parse(arg,line,&db.GetSchema());
// find any external references and store them in the database.
// this helps us emulate STEPs INVERSE fields.
for (size_t i = 0; i < conv_args->GetSize(); ++i) {
const EXPRESS::DataType* t = conv_args->operator [](i);
if (const EXPRESS::ENTITY* e = t->ToPtr<EXPRESS::ENTITY>()) {
db.MarkRef(*e,id);
}
}
}
// ------------------------------------------------------------------------------------------------
STEP::LazyObject::~LazyObject()
{
// 'obj' always remains in our possession, so there is
// no need for a smart pointer type.
delete obj;
delete conv_args;
}
// ------------------------------------------------------------------------------------------------
void STEP::LazyObject::LazyInit() const
{
const EXPRESS::ConversionSchema& schema = db.GetSchema();
STEP::ConvertObjectProc proc = schema.GetConverterProc(type);
if (!proc) {
throw STEP::TypeError("unknown object type: " + type,id,line);
}
// if the converter fails, it should throw an exception, but it should never return NULL
try {
obj = proc(db,*conv_args);
}
catch(const TypeError& t) {
// augment line and entity information
throw TypeError(t.what(),id,line);
}
++db.evaluated_count;
ai_assert(obj);
// store the original id in the object instance
obj->SetID(id);
}

View File

@ -0,0 +1,64 @@
/*
Open Asset Import Library (ASSIMP)
----------------------------------------------------------------------
Copyright (c) 2006-2010, ASSIMP Development Team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the ASSIMP Development Team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#ifndef INCLUDED_AI_STEPFILEREADER_H
#define INCLUDED_AI_STEPFILEREADER_H
#include "STEPFile.h"
namespace Assimp {
namespace STEP {
// ### Parsing a STEP file is a twofold procedure ###
// --------------------------------------------------------------------------
// 1) read file header and return to caller, who checks if the
// file is of a supported schema ..
DB* ReadFileHeader(boost::shared_ptr<IOStream> stream);
// --------------------------------------------------------------------------
// 2) read the actual file contents using a user-supplied set of
// conversion functions to interpret the data.
void ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme);
} // ! STEP
} // ! Assimp
#endif

View File

@ -665,12 +665,37 @@ enum aiComponent
// ---------------------------------------------------------------------------
/** Ogre Importer will try to load this Materialfile
* Ogre Mehs contain only the MaterialName, not the MaterialFile. If there
/** @brief Ogre Importer will try to load this Materialfile.
*
* Ogre Meshes contain only the MaterialName, not the MaterialFile. If there
* is no material file with the same name as the material, Ogre Importer will
* try to load this file and search the material in it.
* <br>
* Property type: String. Default value: guessed.
*/
#define AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE "IMPORT_OGRE_MATERIAL_FILE"
// ---------------------------------------------------------------------------
/** @brief Specfies whether the IFC loader will skip over IfcSpace elements.
*
* IfcSpace elements (and their geometric representations) are used to
* represent, well, free space in a building storey.<br>
* Property type: Bool. Default value: true.
*/
#define AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS "IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS"
// ---------------------------------------------------------------------------
/** @brief Specfies whether the IFC loader will skip over
* shape representations of type 'Curve2D'.
*
* A lot of files contain both a faceted mesh representation and a outline
* with a presentation type of 'Curve2D'. Currently Assimp doesn't convert those,
* so turning this option off just clutters the log with errors.<br>
* Property type: Bool. Default value: true.
*/
#define AI_CONFIG_IMPORT_IFC_SKIP_CURVE_REPRESENTATIONS "IMPORT_IFC_SKIP_CURVE_REPRESENTATIONS"
#endif // !! AI_CONFIG_H_INC

View File

@ -0,0 +1,281 @@
#!/usr/bin/env python3
# -*- Coding: UTF-8 -*-
# ---------------------------------------------------------------------------
# Open Asset Import Library (ASSIMP)
# ---------------------------------------------------------------------------
#
# Copyright (c) 2006-2010, ASSIMP Development Team
#
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms,
# with or without modification, are permitted provided that the following
# conditions are met:
#
# * Redistributions of source code must retain the above
# copyright notice, this list of conditions and the
# following disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the
# following disclaimer in the documentation and/or other
# materials provided with the distribution.
#
# * Neither the name of the ASSIMP team, nor the names of its
# contributors may be used to endorse or promote products
# derived from this software without specific prior
# written permission of the ASSIMP Development Team.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# ---------------------------------------------------------------------------
"""Generate the C++ glue code needed to map EXPRESS to C++"""
import sys, os, re
input_template_h = 'IFCReaderGen.h.template'
input_template_cpp = 'IFCReaderGen.cpp.template'
output_file_h = os.path.join('..','..','code','IFCReaderGen.h')
output_file_cpp = os.path.join('..','..','code','IFCReaderGen.cpp')
template_entity_predef = '\tstruct {entity};\n'
template_entity_predef_ni = '\ttypedef NotImplemented {entity}; // (not currently used by Assimp)\n'
template_entity = r"""
// C++ wrapper for {entity}
struct {entity} : {parent} ObjectHelper<{entity},{argcnt}> {{
{fields}
}};"""
template_entity_ni = ''
template_type = r"""
// C++ wrapper type for {type}
typedef {real_type} {type};"""
template_stub_decl = '\tDECL_CONV_STUB({type});\n'
template_schema = '\t\tSchemaEntry("{normalized_name}",&STEP::ObjectHelper<{type},{argcnt}>::Construct )\n'
template_schema_type = '\t\tSchemaEntry("{normalized_name}",NULL )\n'
template_converter = r"""
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<{type}>(const DB& db, const LIST& params, {type}* in)
{{
{contents}
}}"""
template_converter_prologue_a = '\tsize_t base = GenericFill(db,params,static_cast<{parent}*>(in));\n'
template_converter_prologue_b = '\tsize_t base = 0;\n'
template_converter_check_argcnt = '\tif (params.GetSize() < {max_arg}) {{ throw STEP::TypeError("expected {max_arg} arguments to {name}"); }}'
template_converter_code_per_field = r""" do {{ // convert the '{fieldname}' argument
const DataType* arg = params[base++];{handle_unset}{convert}
}} while(0);
"""
template_allow_optional = r"""
if (dynamic_cast<const UNSET*>(&*arg)) break;"""
template_allow_derived = r"""
if (dynamic_cast<const ISDERIVED*>(&*arg)) {{ in->ObjectHelper<Assimp::IFC::{type},{argcnt}>::aux_is_derived[{argnum}]=true; break; }}"""
template_convert_single = r"""
try {{ GenericConvert( in->{name}, *arg, db ); break; }}
catch (const TypeError& t) {{ throw TypeError(t.what() + std::string(" - expected argument {argnum} to {classname} to be a `{full_type}`")); }}"""
template_converter_ommitted = '// this data structure is not used yet, so there is no code generated to fill its members\n'
template_converter_epilogue = '\treturn base;'
import ExpressReader
def get_list_bounds(collection_spec):
start,end = [(int(n) if n!='?' else 0) for n in re.findall(r'(\d+|\?)',collection_spec)]
return start,end
def get_cpp_type(field,schema):
isobjref = field.type in schema.entities
base = field.type
if isobjref:
base = 'Lazy< '+(base if base in schema.whitelist else 'NotImplemented')+' >'
if field.collection:
start,end = get_list_bounds(field.collection)
base = 'ListOf< {0}, {1}, {2} >'.format(base,start,end)
if not isobjref:
base += '::Out'
if field.optional:
base = 'Maybe< '+base+' >'
return base
def generate_fields(entity,schema):
fields = []
for e in entity.members:
fields.append('\t\t{type} {name};'.format(type=get_cpp_type(e,schema),name=e.name))
return '\n'.join(fields)
def handle_unset_args(field,entity,schema,argnum):
n = ''
# if someone derives from this class, check for derived fields.
if any(entity.name==e.parent for e in schema.entities.values()):
n += template_allow_derived.format(type=entity.name,argcnt=len(entity.members),argnum=argnum)
if not field.optional:
return n+''
return n+template_allow_optional.format()
def get_single_conversion(field,schema,argnum=0,classname='?'):
typen = field.type
name = field.name
if field.collection:
typen = 'LIST'
return template_convert_single.format(type=typen,name=name,argnum=argnum,classname=classname,full_type=field.fullspec)
def count_args_up(entity,schema):
return len(entity.members) + (count_args_up(schema.entities[entity.parent],schema) if entity.parent else 0)
def resolve_base_type(base,schema):
if base in ('INTEGER','REAL','STRING','ENUMERATION','BOOLEAN','NUMBER', 'SELECT','LOGICAL'):
return base
if base in schema.types:
return resolve_base_type(schema.types[base].equals,schema)
print(base)
return None
def gen_type_struct(typen,schema):
base = resolve_base_type(typen.equals,schema)
if not base:
return ''
if typen.aggregate:
start,end = get_list_bounds(typen.aggregate)
base = 'ListOf< {0}, {1}, {2} >'.format(base,start,end)
return template_type.format(type=typen.name,real_type=base)
def gen_converter(entity,schema):
max_arg = count_args_up(entity,schema)
arg_idx = arg_idx_ofs = max_arg - len(entity.members)
code = template_converter_prologue_a.format(parent=entity.parent) if entity.parent else template_converter_prologue_b
if entity.name in schema.blacklist_partial:
return code+template_converter_ommitted+template_converter_epilogue;
code +=template_converter_check_argcnt.format(max_arg=max_arg,name=entity.name)
for field in entity.members:
code += template_converter_code_per_field.format(fieldname=field.name,
handle_unset=handle_unset_args(field,entity,schema,arg_idx-arg_idx_ofs),
convert=get_single_conversion(field,schema,arg_idx,entity.name))
arg_idx += 1
return code+template_converter_epilogue
def get_base_classes(e,schema):
def addit(e,out):
if e.parent:
out.append(e.parent)
addit(schema.entities[e.parent],out)
res = []
addit(e,res)
return list(reversed(res))
def get_derived(e,schema):
def get_deriv(e,out): # bit slow, but doesn't matter here
s = [ee for ee in schema.entities.values() if ee.parent == e.name]
for sel in s:
out.append(sel.name)
get_deriv(sel,out)
res = []
get_deriv(e,res)
return res
def get_hierarchy(e,schema):
return get_derived(e.schema)+[e.name]+get_base_classes(e,schema)
def sort_entity_list(schema):
deps = []
entities = schema.entities
for e in entities.values():
deps += get_base_classes(e,schema)+[e.name]
checked = []
for e in deps:
if e not in checked:
checked.append(e)
return [entities[e] for e in checked]
def work(filename):
schema = ExpressReader.read(filename,silent=True)
entities, stub_decls, schema_table, converters, typedefs, predefs = '','',[],'','',''
whitelist = []
with open('entitylist.txt', 'rt') as inp:
whitelist = [n.strip() for n in inp.read().split('\n') if n[:1]!='#' and n.strip()]
schema.whitelist = set()
schema.blacklist_partial = set()
for ename in whitelist:
try:
e = schema.entities[ename]
except KeyError:
# type, not entity
continue
for base in [e.name]+get_base_classes(e,schema):
schema.whitelist.add(base)
for base in get_derived(e,schema):
schema.blacklist_partial.add(base)
schema.blacklist_partial -= schema.whitelist
schema.whitelist |= schema.blacklist_partial
# uncomment this to disable automatic code reduction based on whitelisting all used entities
# (blacklisted entities are those who are in the whitelist and may be instanced, but will
# only be accessed through a pointer to a base-class.
#schema.whitelist = set(schema.entities.keys())
#schema.blacklist_partial = set()
for ntype in schema.types.values():
typedefs += gen_type_struct(ntype,schema)
schema_table.append(template_schema_type.format(normalized_name=ntype.name.lower()))
sorted_entities = sort_entity_list(schema)
for entity in sorted_entities:
parent = entity.parent+',' if entity.parent else ''
if entity.name in schema.whitelist:
converters += template_converter.format(type=entity.name,contents=gen_converter(entity,schema))
schema_table.append(template_schema.format(type=entity.name,normalized_name=entity.name.lower(),argcnt=len(entity.members)))
entities += template_entity.format(entity=entity.name,argcnt=len(entity.members),parent=parent,fields=generate_fields(entity,schema))
predefs += template_entity_predef.format(entity=entity.name)
stub_decls += template_stub_decl.format(type=entity.name)
else:
entities += template_entity_ni.format(entity=entity.name)
predefs += template_entity_predef_ni.format(entity=entity.name)
schema_table.append(template_schema.format(type="NotImplemented",normalized_name=entity.name.lower(),argcnt=0))
schema_table = ','.join(schema_table)
with open(input_template_h,'rt') as inp:
with open(output_file_h,'wt') as outp:
# can't use format() here since the C++ code templates contain single, unescaped curly brackets
outp.write(inp.read().replace('{predefs}',predefs).replace('{types}',typedefs).replace('{entities}',entities).replace('{converter-decl}',stub_decls))
with open(input_template_cpp,'rt') as inp:
with open(output_file_cpp,'wt') as outp:
outp.write(inp.read().replace('{schema-static-table}',schema_table).replace('{converter-impl}',converters))
if __name__ == "__main__":
sys.exit(work(sys.argv[1] if len(sys.argv)>1 else 'schema.exp'))

View File

@ -0,0 +1,120 @@
#!/usr/bin/env python3
# -*- Coding: UTF-8 -*-
# ---------------------------------------------------------------------------
# Open Asset Import Library (ASSIMP)
# ---------------------------------------------------------------------------
#
# Copyright (c) 2006-2010, ASSIMP Development Team
#
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms,
# with or without modification, are permitted provided that the following
# conditions are met:
#
# * Redistributions of source code must retain the above
# copyright notice, this list of conditions and the
# following disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the
# following disclaimer in the documentation and/or other
# materials provided with the distribution.
#
# * Neither the name of the ASSIMP team, nor the names of its
# contributors may be used to endorse or promote products
# derived from this software without specific prior
# written permission of the ASSIMP Development Team.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# ---------------------------------------------------------------------------
"""Parse an EXPRESS file and extract basic information on all
entities and data types contained"""
import sys, os, re
re_match_entity = re.compile(r"""
ENTITY\s+(\w+)\s* # 'ENTITY foo'
.*? # skip SUPERTYPE-of
(?:SUBTYPE\s+OF\s+\((\w+)\))?; # 'SUBTYPE OF (bar);' or simply ';'
(.*?) # 'a : atype;' (0 or more lines like this)
(?:(?:INVERSE|UNIQUE|WHERE)\s*$.*?)? # skip the INVERSE, UNIQUE, WHERE clauses and everything behind
END_ENTITY;
""",re.VERBOSE|re.DOTALL|re.MULTILINE)
re_match_type = re.compile(r"""
TYPE\s+(\w+?)\s*=\s*((?:LIST|SET)\s*\[\d+:[\d?]+\]\s*OF)?(?:\s*UNIQUE)?\s*(\w+) # TYPE foo = LIST[1:2] of blub
(?:(?<=ENUMERATION)\s*OF\s*\((.*?)\))?
.*? # skip the WHERE clause
END_TYPE;
""",re.VERBOSE|re.DOTALL)
re_match_field = re.compile(r"""
\s+(\w+?)\s*:\s*(OPTIONAL)?\s*((?:LIST|SET)\s*\[\d+:[\d?]+\]\s*OF)?(?:\s*UNIQUE)?\s*(\w+?);
""",re.VERBOSE|re.DOTALL)
class Schema:
def __init__(self):
self.entities = {}
self.types = {}
class Entity:
def __init__(self,name,parent,members):
self.name = name
self.parent = parent
self.members = members
class Field:
def __init__(self,name,type,optional,collection):
self.name = name
self.type = type
self.optional = optional
self.collection = collection
self.fullspec = (self.collection+' ' if self.collection else '') + self.type
class Type:
def __init__(self,name,aggregate,equals,enums):
self.name = name
self.aggregate = aggregate
self.equals = equals
self.enums = enums
def read(filename,silent=False):
schema = Schema()
with open(filename,'rt') as inp:
contents = inp.read()
types = re.findall(re_match_type,contents)
for name,aggregate,equals,enums in types:
schema.types[name] = Type(name,aggregate,equals,enums)
entities = re.findall(re_match_entity,contents)
for name,parent,fields_raw in entities:
print('process entity {0}, parent is {1}'.format(name,parent)) if not silent else None
fields = re.findall(re_match_field,fields_raw)
members = [Field(name,type,opt,coll) for name, opt, coll, type in fields]
print(' got {0} fields'.format(len(members))) if not silent else None
schema.entities[name] = Entity(name,parent,members)
return schema
if __name__ == "__main__":
sys.exit(read(sys.argv[1] if len(sys.argv)>1 else 'schema.exp'))

View File

@ -0,0 +1,79 @@
/*
Open Asset Import Library (ASSIMP)
----------------------------------------------------------------------
Copyright (c) 2006-2010, ASSIMP Development Team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the ASSIMP Development Team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** MACHINE-GENERATED by scripts/ICFImporter/CppGenerator.py */
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCReaderGen.h"
namespace Assimp {
using namespace IFC;
namespace {
typedef EXPRESS::ConversionSchema::SchemaEntry SchemaEntry;
const SchemaEntry schema_raw[] = {
{schema-static-table}
};
}
// -----------------------------------------------------------------------------------------------------------
void IFC::GetSchema(EXPRESS::ConversionSchema& out)
{
out = EXPRESS::ConversionSchema(schema_raw);
}
namespace STEP {
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<NotImplemented>(const STEP::DB& db, const LIST& params, NotImplemented* in)
{
return 0;
}
{converter-impl}
} // ! STEP
} // ! Assimp
#endif

View File

@ -0,0 +1,91 @@
/*
Open Asset Import Library (ASSIMP)
----------------------------------------------------------------------
Copyright (c) 2006-2010, ASSIMP Development Team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the ASSIMP Development Team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** MACHINE-GENERATED by scripts/ICFImporter/CppGenerator.py */
#ifndef INCLUDED_IFC_READER_GEN_H
#define INCLUDED_IFC_READER_GEN_H
#include "STEPFile.h"
namespace Assimp {
namespace IFC {
using namespace STEP;
using namespace STEP::EXPRESS;
struct NotImplemented : public ObjectHelper<NotImplemented,0> {
};
// ******************************************************************************
// IFC Custom data types
// ******************************************************************************
{types}
// ******************************************************************************
// IFC Entities
// ******************************************************************************
{predefs}
{entities}
void GetSchema(EXPRESS::ConversionSchema& out);
} //! IFC
namespace STEP {
// ******************************************************************************
// Converter stubs
// ******************************************************************************
#define DECL_CONV_STUB(type) template <> size_t GenericFill<IFC::type>(const STEP::DB& db, const EXPRESS::LIST& params, IFC::type* in)
{converter-decl}
#undef DECL_CONV_STUB
} //! STEP
} //! Assimp
#endif // INCLUDED_IFC_READER_GEN_H

View File

@ -0,0 +1,184 @@
# ==============================================================================
# List of IFC structures needed by Assimp
# ==============================================================================
# use genentitylist.sh to update this list
# This machine-generated list is not complete, it lacks many intermediate
# classes in the inheritance hierarchy. Those are magically augmented by the
# code generator. Also, the names of all used entities need to be present
# in the source code for this to work.
IfcRepresentationMap
IfcProductRepresentation
IfcUnitAssignment
IfcClosedShell
IfcDoor
IfcProject
IfcRepresentationItem
IfcAxis2Placement
IfcProduct
IfcProject
IfcSIUnit
IfcColourRgb
IfcColourOrFactor
IfcColourRgb
IfcCartesianPoint
IfcDirection
IfcAxis2Placement3D
IfcAxis2Placement2D
IfcAxis2Placement
IfcAxis2Placement3D
IfcAxis2Placement2D
IfcRepresentationContext
IfcGeometricRepresentationContext
IfcCartesianTransformationOperator
IfcCartesianTransformationOperator3D
IfcPolyLoop
IfcCartesianPoint
IfcConnectedFaceSet
IfcFace
IfcFaceBound
IfcPolyLoop
IfcPolyline
IfcCartesianPoint
IfcArbitraryClosedProfileDef
IfcPolyline
IfcArbitraryOpenProfileDef
IfcPolyline
IfcParameterizedProfileDef
IfcRectangleProfileDef
IfcExtrudedAreaSolid
IfcArbitraryClosedProfileDef
IfcArbitraryOpenProfileDef
IfcParameterizedProfileDef
IfcSweptAreaSolid
IfcExtrudedAreaSolid
IfcBooleanResult
IfcBooleanClippingResult
IfcBooleanResult
IfcSweptAreaSolid
IfcRepresentationItem
IfcStyledItem
IfcPresentationStyleAssignment
IfcPresentationStyleSelect
IfcSurfaceStyle
IfcSurfaceStyleElementSelect
IfcSurfaceStyleShading
IfcSurfaceStyleRendering
IfcSurfaceStyleWithTextures
IfcTopologicalRepresentationItem
IfcConnectedFaceSet
IfcGeometricRepresentationItem
IfcShellBasedSurfaceModel
IfcShell
IfcConnectedFaceSet
IfcSweptAreaSolid
IfcManifoldSolidBrep
IfcBooleanResult
IfcRepresentationItem
IfcTopologicalRepresentationItem
IfcGeometricRepresentationItem
IfcObjectPlacement
IfcLocalPlacement
IfcMappedItem
IfcRepresentation
IfcRepresentationItem
IfcProduct
IfcSpace
IfcRepresentation
IfcRepresentationItem
IfcMappedItem
IfcProduct
IfcRelContainedInSpatialStructure
IfcProduct
IfcRelAggregates
IfcObjectDefinition
IfcProduct
IfcSpatialStructureElement
IfcRelAggregates
IfcObjectDefinition
IfcProject
IfcRepresentationItem
IfcAxis2Placement
IfcProduct
IfcProject
IfcSIUnit
IfcColourRgb
IfcColourOrFactor
IfcColourRgb
IfcCartesianPoint
IfcDirection
IfcAxis2Placement3D
IfcAxis2Placement2D
IfcAxis2Placement
IfcAxis2Placement3D
IfcAxis2Placement2D
IfcRepresentationContext
IfcGeometricRepresentationContext
IfcCartesianTransformationOperator
IfcCartesianTransformationOperator3D
IfcPolyLoop
IfcCartesianPoint
IfcConnectedFaceSet
IfcFace
IfcFaceBound
IfcPolyLoop
IfcPolyline
IfcCartesianPoint
IfcArbitraryClosedProfileDef
IfcPolyline
IfcArbitraryOpenProfileDef
IfcPolyline
IfcParameterizedProfileDef
IfcRectangleProfileDef
IfcExtrudedAreaSolid
IfcArbitraryClosedProfileDef
IfcArbitraryOpenProfileDef
IfcParameterizedProfileDef
IfcSweptAreaSolid
IfcExtrudedAreaSolid
IfcBooleanResult
IfcBooleanClippingResult
IfcBooleanResult
IfcSweptAreaSolid
IfcRepresentationItem
IfcStyledItem
IfcPresentationStyleAssignment
IfcPresentationStyleSelect
IfcSurfaceStyle
IfcSurfaceStyleElementSelect
IfcSurfaceStyleShading
IfcSurfaceStyleRendering
IfcSurfaceStyleWithTextures
IfcTopologicalRepresentationItem
IfcConnectedFaceSet
IfcGeometricRepresentationItem
IfcShellBasedSurfaceModel
IfcShell
IfcConnectedFaceSet
IfcSweptAreaSolid
IfcManifoldSolidBrep
IfcBooleanResult
IfcRepresentationItem
IfcTopologicalRepresentationItem
IfcGeometricRepresentationItem
IfcObjectPlacement
IfcLocalPlacement
IfcMappedItem
IfcRepresentation
IfcRepresentationItem
IfcProduct
IfcSpace
IfcRepresentation
IfcRepresentationItem
IfcMappedItem
IfcProduct
IfcRelContainedInSpatialStructure
IfcProduct
IfcRelAggregates
IfcObjectDefinition
IfcProduct
IfcSpatialStructureElement
IfcRelAggregates
IfcObjectDefinition

View File

@ -0,0 +1,2 @@
#!/bin/sh
grep -E 'IFC::Ifc([A-Z][a-z]*)+' -o ../../code/IFCLoader.cpp | uniq | sed s/IFC::// > output.txt

View File

@ -1942,6 +1942,46 @@
>
</File>
</Filter>
<Filter
Name="icf"
>
<File
RelativePath="..\..\code\IFCLoader.cpp"
>
</File>
<File
RelativePath="..\..\code\IFCLoader.h"
>
</File>
<File
RelativePath="..\..\code\IFCReaderGen.cpp"
>
<FileConfiguration
Name="debug|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/bigobj"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\code\IFCReaderGen.h"
>
</File>
<File
RelativePath="..\..\code\STEPFile.h"
>
</File>
<File
RelativePath="..\..\code\STEPFileReader.cpp"
>
</File>
<File
RelativePath="..\..\code\STEPFileReader.h"
>
</File>
</Filter>
</Filter>
<Filter
Name="postprocessing"