+ 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
|
BlenderModifier.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
SOURCE_GROUP(IFC FILES
|
||||||
|
IFCLoader.cpp
|
||||||
|
IFCLoader.h
|
||||||
|
IFCReaderGen.cpp
|
||||||
|
IFCReaderGen.h
|
||||||
|
STEPFile.h
|
||||||
|
STEPFileReader.h
|
||||||
|
STEPFileReader.cpp
|
||||||
|
)
|
||||||
|
|
||||||
SOURCE_GROUP( PostProcessing FILES
|
SOURCE_GROUP( PostProcessing FILES
|
||||||
CalcTangentsProcess.cpp
|
CalcTangentsProcess.cpp
|
||||||
CalcTangentsProcess.h
|
CalcTangentsProcess.h
|
||||||
|
@ -742,6 +752,13 @@ ADD_LIBRARY( assimp SHARED
|
||||||
DeboneProcess.h
|
DeboneProcess.h
|
||||||
ColladaExporter.h
|
ColladaExporter.h
|
||||||
ColladaExporter.cpp
|
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:
|
# Necessary to show the headers in the project when using the VC++ generator:
|
||||||
BoostWorkaround/boost/math/common_factor_rt.hpp
|
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 ...
|
* further imports with the same Importer instance could fail/crash/burn ...
|
||||||
*/
|
*/
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
#define ASSIMP_CATCH_GLOBAL_EXCEPTIONS
|
#ifndef ASSIMP_BUILD_DEBUG
|
||||||
|
# define ASSIMP_CATCH_GLOBAL_EXCEPTIONS
|
||||||
|
#endif
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Internal headers
|
// Internal headers
|
||||||
|
@ -184,6 +185,9 @@ using namespace Assimp::Formatter;
|
||||||
#ifndef ASSIMP_BUILD_NO_NDO_IMPORTER
|
#ifndef ASSIMP_BUILD_NO_NDO_IMPORTER
|
||||||
# include "NDOLoader.h"
|
# include "NDOLoader.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
|
||||||
|
# include "IFCLoader.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Post processing-Steps
|
// Post processing-Steps
|
||||||
|
@ -432,6 +436,9 @@ Importer::Importer()
|
||||||
#if (!defined ASSIMP_BUILD_NO_NDO_IMPORTER)
|
#if (!defined ASSIMP_BUILD_NO_NDO_IMPORTER)
|
||||||
pimpl->mImporter.push_back( new NDOImporter() );
|
pimpl->mImporter.push_back( new NDOImporter() );
|
||||||
#endif
|
#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
|
// Add an instance of each post processing step here in the order
|
||||||
|
|
|
@ -189,7 +189,7 @@ public:
|
||||||
return &cur;
|
return &cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& operator* () const {
|
std::string operator* () const {
|
||||||
return cur;
|
return cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,21 +48,54 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "StringComparison.h"
|
#include "StringComparison.h"
|
||||||
namespace Assimp {
|
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>
|
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');
|
return (in == (char_t)' ' || in == (char_t)'\t');
|
||||||
}
|
}
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_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');
|
return (in == (char_t)'\r' || in == (char_t)'\n' || in == (char_t)'\0');
|
||||||
}
|
}
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
template <class char_t>
|
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);
|
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
|
/** @brief Ogre Importer will try to load this Materialfile.
|
||||||
* Ogre Mehs contain only the MaterialName, not the MaterialFile. If there
|
*
|
||||||
|
* 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
|
* 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.
|
* 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"
|
#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
|
#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>
|
</File>
|
||||||
</Filter>
|
</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>
|
||||||
<Filter
|
<Filter
|
||||||
Name="postprocessing"
|
Name="postprocessing"
|
||||||
|
|
Loading…
Reference in New Issue