+ 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-9d2fd5bffc1fpull/1/head
parent
a83183d95f
commit
1400ae79e7
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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 ...
|
||||
*/
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#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
|
||||
|
|
|
@ -189,7 +189,7 @@ public:
|
|||
return &cur;
|
||||
}
|
||||
|
||||
const std::string& operator* () const {
|
||||
std::string operator* () const {
|
||||
return cur;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 = ∈
|
||||
}
|
||||
};
|
||||
|
||||
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
|
|
@ -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 <rim(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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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'))
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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'))
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
grep -E 'IFC::Ifc([A-Z][a-z]*)+' -o ../../code/IFCLoader.cpp | uniq | sed s/IFC::// > output.txt
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue