- IFC: use smart pointers to keep STEP-SELECT entities in the converted output data structures. This allows us to free the original parameter tuples early as ownership of their members can be transferred. This cuts down memory overhead to 8x (assuming a typical x64 builds) and reduces loading time on average by ~5% as measured on my system.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1019 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2011-05-31 14:23:43 +00:00
parent 0db3f8b3f4
commit 1e2dd3eefc
6 changed files with 294 additions and 290 deletions

View File

@ -327,7 +327,7 @@ void ProcessSpatialStructures(ConversionData& conv);
aiNode* ProcessSpatialStructure(aiNode* parent, const IFC::IfcProduct& el ,ConversionData& conv); aiNode* ProcessSpatialStructure(aiNode* parent, const IFC::IfcProduct& el ,ConversionData& conv);
void ProcessProductRepresentation(const IFC::IfcProduct& el, aiNode* nd, ConversionData& conv); void ProcessProductRepresentation(const IFC::IfcProduct& el, aiNode* nd, ConversionData& conv);
void MakeTreeRelative(ConversionData& conv); void MakeTreeRelative(ConversionData& conv);
void ConvertUnit(const EXPRESS::DataType* dt,ConversionData& conv); void ConvertUnit(const EXPRESS::DataType& dt,ConversionData& conv);
void ProcessSweptAreaSolid(const IFC::IfcSweptAreaSolid& swept, TempMesh& meshout, ConversionData& conv); void ProcessSweptAreaSolid(const IFC::IfcSweptAreaSolid& swept, TempMesh& meshout, ConversionData& conv);
} // anon } // anon
@ -560,7 +560,7 @@ void ConvertUnit(const IFC::IfcNamedUnit& unit,ConversionData& conv)
if(convu->UnitType == "PLANEANGLEUNIT") { if(convu->UnitType == "PLANEANGLEUNIT") {
try { try {
conv.angle_scale = convu->ConversionFactor->ValueComponent->To<EXPRESS::REAL>(); conv.angle_scale = convu->ConversionFactor->ValueComponent->To<EXPRESS::REAL>();
ConvertUnit(convu->ConversionFactor->UnitComponent,conv); ConvertUnit(*convu->ConversionFactor->UnitComponent,conv);
IFCImporter::LogDebug("got units used for angles"); IFCImporter::LogDebug("got units used for angles");
} }
catch(std::bad_cast&) { catch(std::bad_cast&) {
@ -571,10 +571,10 @@ void ConvertUnit(const IFC::IfcNamedUnit& unit,ConversionData& conv)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertUnit(const EXPRESS::DataType* dt,ConversionData& conv) void ConvertUnit(const EXPRESS::DataType& dt,ConversionData& conv)
{ {
try { try {
const EXPRESS::ENTITY& e = dt->To<IFC::ENTITY>(); const EXPRESS::ENTITY& e = dt.To<IFC::ENTITY>();
const IFC::IfcNamedUnit& unit = e.ResolveSelect<IFC::IfcNamedUnit>(conv.db); const IFC::IfcNamedUnit& unit = e.ResolveSelect<IFC::IfcNamedUnit>(conv.db);
if(unit.UnitType != "LENGTHUNIT" && unit.UnitType != "PLANEANGLEUNIT") { if(unit.UnitType != "LENGTHUNIT" && unit.UnitType != "PLANEANGLEUNIT") {
@ -594,7 +594,7 @@ void SetUnits(ConversionData& conv)
{ {
// see if we can determine the coordinate space used to express. // see if we can determine the coordinate space used to express.
for(size_t i = 0; i < conv.proj.UnitsInContext->Units.size(); ++i ) { for(size_t i = 0; i < conv.proj.UnitsInContext->Units.size(); ++i ) {
ConvertUnit(conv.proj.UnitsInContext->Units[i],conv); ConvertUnit(*conv.proj.UnitsInContext->Units[i],conv);
} }
} }
@ -608,9 +608,9 @@ void ConvertColor(aiColor4D& out, const IFC::IfcColourRgb& in)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertColor(aiColor4D& out, const IFC::IfcColourOrFactor* in,ConversionData& conv,const aiColor4D* base) void ConvertColor(aiColor4D& out, const IFC::IfcColourOrFactor& in,ConversionData& conv,const aiColor4D* base)
{ {
if (const EXPRESS::REAL* const r = in->ToPtr<EXPRESS::REAL>()) { if (const EXPRESS::REAL* const r = in.ToPtr<EXPRESS::REAL>()) {
out.r = out.g = out.b = *r; out.r = out.g = out.b = *r;
if(base) { if(base) {
out.r *= base->r; out.r *= base->r;
@ -620,7 +620,7 @@ void ConvertColor(aiColor4D& out, const IFC::IfcColourOrFactor* in,ConversionDat
} }
else out.a = 1.0; else out.a = 1.0;
} }
else if (const IFC::IfcColourRgb* const rgb = in->ResolveSelectPtr<IFC::IfcColourRgb>(conv.db)) { else if (const IFC::IfcColourRgb* const rgb = in.ResolveSelectPtr<IFC::IfcColourRgb>(conv.db)) {
ConvertColor(out,*rgb); ConvertColor(out,*rgb);
} }
else { else {
@ -2108,7 +2108,7 @@ void FillMaterial(MaterialHelper* mat,const IFC::IfcSurfaceStyle* surf,Conversio
mat->AddProperty(&name,AI_MATKEY_NAME); mat->AddProperty(&name,AI_MATKEY_NAME);
// now see which kinds of surface information are present // now see which kinds of surface information are present
BOOST_FOREACH(const IFC::IfcSurfaceStyleElementSelect* sel2, surf->Styles) { BOOST_FOREACH(boost::shared_ptr< const IFC::IfcSurfaceStyleElementSelect > sel2, surf->Styles) {
if (const IFC::IfcSurfaceStyleShading* shade = sel2->ResolveSelectPtr<IFC::IfcSurfaceStyleShading>(conv.db)) { if (const IFC::IfcSurfaceStyleShading* shade = sel2->ResolveSelectPtr<IFC::IfcSurfaceStyleShading>(conv.db)) {
aiColor4D col_base,col; aiColor4D col_base,col;
@ -2123,22 +2123,22 @@ void FillMaterial(MaterialHelper* mat,const IFC::IfcSurfaceStyle* surf,Conversio
} }
if (ren->DiffuseColour) { if (ren->DiffuseColour) {
ConvertColor(col, ren->DiffuseColour.Get(),conv,&col_base); ConvertColor(col, *ren->DiffuseColour.Get(),conv,&col_base);
mat->AddProperty(&col,1, AI_MATKEY_COLOR_DIFFUSE); mat->AddProperty(&col,1, AI_MATKEY_COLOR_DIFFUSE);
} }
if (ren->SpecularColour) { if (ren->SpecularColour) {
ConvertColor(col, ren->SpecularColour.Get(),conv,&col_base); ConvertColor(col, *ren->SpecularColour.Get(),conv,&col_base);
mat->AddProperty(&col,1, AI_MATKEY_COLOR_SPECULAR); mat->AddProperty(&col,1, AI_MATKEY_COLOR_SPECULAR);
} }
if (ren->TransmissionColour) { if (ren->TransmissionColour) {
ConvertColor(col, ren->TransmissionColour.Get(),conv,&col_base); ConvertColor(col, *ren->TransmissionColour.Get(),conv,&col_base);
mat->AddProperty(&col,1, AI_MATKEY_COLOR_TRANSPARENT); mat->AddProperty(&col,1, AI_MATKEY_COLOR_TRANSPARENT);
} }
if (ren->ReflectionColour) { if (ren->ReflectionColour) {
ConvertColor(col, ren->ReflectionColour.Get(),conv,&col_base); ConvertColor(col, *ren->ReflectionColour.Get(),conv,&col_base);
mat->AddProperty(&col,1, AI_MATKEY_COLOR_REFLECTIVE); mat->AddProperty(&col,1, AI_MATKEY_COLOR_REFLECTIVE);
} }
@ -2185,7 +2185,7 @@ unsigned int ProcessMaterials(const IFC::IfcRepresentationItem& item, Conversion
for(;range.first != range.second; ++range.first) { for(;range.first != range.second; ++range.first) {
if(const IFC::IfcStyledItem* const styled = conv.db.GetObject((*range.first).second)->ToPtr<IFC::IfcStyledItem>()) { if(const IFC::IfcStyledItem* const styled = conv.db.GetObject((*range.first).second)->ToPtr<IFC::IfcStyledItem>()) {
BOOST_FOREACH(const IFC::IfcPresentationStyleAssignment& as, styled->Styles) { BOOST_FOREACH(const IFC::IfcPresentationStyleAssignment& as, styled->Styles) {
BOOST_FOREACH(const IFC::IfcPresentationStyleSelect* sel, as.Styles) { BOOST_FOREACH(boost::shared_ptr<const IFC::IfcPresentationStyleSelect> sel, as.Styles) {
if (const IFC::IfcSurfaceStyle* const surf = sel->ResolveSelectPtr<IFC::IfcSurfaceStyle>(conv.db)) { if (const IFC::IfcSurfaceStyle* const surf = sel->ResolveSelectPtr<IFC::IfcSurfaceStyle>(conv.db)) {
const std::string side = static_cast<std::string>(surf->Side); const std::string side = static_cast<std::string>(surf->Side);
@ -2237,7 +2237,7 @@ bool ProcessGeometricItem(const IFC::IfcGeometricRepresentationItem& geo, std::v
{ {
TempMesh meshtmp; TempMesh meshtmp;
if(const IFC::IfcShellBasedSurfaceModel* shellmod = geo.ToPtr<IFC::IfcShellBasedSurfaceModel>()) { if(const IFC::IfcShellBasedSurfaceModel* shellmod = geo.ToPtr<IFC::IfcShellBasedSurfaceModel>()) {
BOOST_FOREACH(const IFC::IfcShell* shell,shellmod->SbsmBoundary) { BOOST_FOREACH(boost::shared_ptr<const IFC::IfcShell> shell,shellmod->SbsmBoundary) {
try { try {
const EXPRESS::ENTITY& e = shell->To<IFC::ENTITY>(); const EXPRESS::ENTITY& e = shell->To<IFC::ENTITY>();
const IFC::IfcConnectedFaceSet& fs = conv.db.MustGetObject(e).To<IFC::IfcConnectedFaceSet>(); const IFC::IfcConnectedFaceSet& fs = conv.db.MustGetObject(e).To<IFC::IfcConnectedFaceSet>();
@ -2589,6 +2589,9 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IFC::IfcProduct& el, Conve
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ProcessSpatialStructures(ConversionData& conv) void ProcessSpatialStructures(ConversionData& conv)
{ {
// XXX add support for multiple sites (i.e. IfcSpatialStructureElements with composition == COMPLEX)
// process all products in the file. it is reasonable to assume that a // process all products in the file. it is reasonable to assume that a
// file that is relevant for us contains at least a site or a building. // file that is relevant for us contains at least a site or a building.
const STEP::DB::ObjectMapByType& map = conv.db.GetObjectsByType(); const STEP::DB::ObjectMapByType& map = conv.db.GetObjectsByType();
@ -2635,6 +2638,17 @@ void ProcessSpatialStructures(ConversionData& conv)
} }
IFCImporter::LogWarn("failed to determine primary site element, taking the first IfcSite");
BOOST_FOREACH(const STEP::LazyObject* lz, *range) {
const IFC::IfcSpatialStructureElement* const prod = lz->ToPtr<IFC::IfcSpatialStructureElement>();
if(!prod) {
continue;
}
conv.out->mRootNode = ProcessSpatialStructure(NULL,*prod,conv,NULL);
return;
}
IFCImporter::ThrowException("failed to determine primary site element"); IFCImporter::ThrowException("failed to determine primary site element");
} }

File diff suppressed because it is too large Load Diff

View File

@ -3113,7 +3113,7 @@ namespace IFC {
// C++ wrapper for IfcRelContainedInSpatialStructure // C++ wrapper for IfcRelContainedInSpatialStructure
struct IfcRelContainedInSpatialStructure : IfcRelConnects, ObjectHelper<IfcRelContainedInSpatialStructure,2> { IfcRelContainedInSpatialStructure() : Object("IfcRelContainedInSpatialStructure") {} struct IfcRelContainedInSpatialStructure : IfcRelConnects, ObjectHelper<IfcRelContainedInSpatialStructure,2> { IfcRelContainedInSpatialStructure() : Object("IfcRelContainedInSpatialStructure") {}
ListOf< Lazy< IfcProduct >, 0, 0 > RelatedElements; ListOf< Lazy< IfcProduct >, 1, 0 > RelatedElements;
Lazy< IfcSpatialStructureElement > RelatingStructure; Lazy< IfcSpatialStructureElement > RelatingStructure;
}; };

View File

@ -159,7 +159,7 @@ namespace STEP {
{ {
public: public:
typedef const DataType* Out; typedef boost::shared_ptr<const DataType> Out;
public: public:
@ -326,18 +326,10 @@ namespace STEP {
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
class LIST : public DataType class LIST : public DataType
{ {
public:
~LIST() {
BOOST_FOREACH(const DataType* dt, members) {
delete dt;
}
}
public: public:
// access a particular list index, throw std::range_error for wrong indices // access a particular list index, throw std::range_error for wrong indices
const DataType* operator[] (size_t index) const { boost::shared_ptr<const DataType> operator[] (size_t index) const {
return members[index]; return members[index];
} }
@ -354,8 +346,7 @@ namespace STEP {
private: private:
// no smart pointer type to avoid any overhead typedef std::vector< boost::shared_ptr<const DataType> > MemberList;
typedef std::vector< const DataType* > MemberList;
MemberList members; MemberList members;
}; };
@ -735,14 +726,14 @@ namespace STEP {
typedef EXPRESS::ENTITY Type; typedef EXPRESS::ENTITY Type;
}; };
template <> struct PickBaseType<EXPRESS::DataType*>; template <> struct PickBaseType< boost::shared_ptr< const EXPRESS::DataType > >;
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
template <typename T> template <typename T>
struct InternGenericConvert { struct InternGenericConvert {
void operator()(T& out, const EXPRESS::DataType& in, const STEP::DB& db) { void operator()(T& out, boost::shared_ptr< const EXPRESS::DataType >& in, const STEP::DB& db) {
try{ try{
out = dynamic_cast< const typename PickBaseType<T>::Type& > ( in ); out = dynamic_cast< const typename PickBaseType<T>::Type& > ( *in );
} }
catch(std::bad_cast&) { catch(std::bad_cast&) {
throw TypeError("type error reading literal field"); throw TypeError("type error reading literal field");
@ -751,15 +742,15 @@ namespace STEP {
}; };
template <> template <>
struct InternGenericConvert<const EXPRESS::DataType*> { struct InternGenericConvert< boost::shared_ptr< const EXPRESS::DataType > > {
void operator()(const EXPRESS::DataType*& out, const EXPRESS::DataType& in, const STEP::DB& db) { void operator()(boost::shared_ptr< const EXPRESS::DataType >& out, boost::shared_ptr< const EXPRESS::DataType >& in, const STEP::DB& db) {
out = &in; out = in;
} }
}; };
template <typename T> template <typename T>
struct InternGenericConvert< Maybe<T> > { struct InternGenericConvert< Maybe<T> > {
void operator()(Maybe<T>& out, const EXPRESS::DataType& in, const STEP::DB& db) { void operator()(Maybe<T>& out, boost::shared_ptr< const EXPRESS::DataType >& in, const STEP::DB& db) {
GenericConvert((T&)out,in,db); GenericConvert((T&)out,in,db);
out.flag_valid(); out.flag_valid();
} }
@ -767,20 +758,19 @@ namespace STEP {
template <typename T,uint64_t min_cnt, uint64_t max_cnt> template <typename T,uint64_t min_cnt, uint64_t max_cnt>
struct InternGenericConvertList { struct InternGenericConvertList {
void operator()(ListOf<T, min_cnt, max_cnt>& out, const EXPRESS::DataType& inp_base, const STEP::DB& db) { void operator()(ListOf<T, min_cnt, max_cnt>& out, boost::shared_ptr< const EXPRESS::DataType >& inp_base, const STEP::DB& db) {
const EXPRESS::LIST* inp = dynamic_cast<const EXPRESS::LIST*>(&inp_base); const EXPRESS::LIST* inp = dynamic_cast<const EXPRESS::LIST*>(inp_base.get());
if (!inp) { if (!inp) {
throw TypeError("type error reading aggregate"); throw TypeError("type error reading aggregate");
} }
// XXX is this really how the EXPRESS notation ([?:3],[1:3]) .. works? // XXX is this really how the EXPRESS notation ([?:3],[1:3]) is intended?
// too many is warning, too few is critical error because the user won't validate this
if (max_cnt && inp->GetSize() > max_cnt) { if (max_cnt && inp->GetSize() > max_cnt) {
DefaultLogger::get()->warn("too many aggregate elements"); DefaultLogger::get()->warn("too many aggregate elements");
} }
else if (inp->GetSize() < min_cnt) { else if (inp->GetSize() < min_cnt) {
throw TypeError("too few aggregate elements"); DefaultLogger::get()->warn("too few aggregate elements");
} }
out.reserve(inp->GetSize()); out.reserve(inp->GetSize());
@ -788,7 +778,7 @@ namespace STEP {
out.push_back( typename ListOf<T, min_cnt, max_cnt>::OutScalar() ); out.push_back( typename ListOf<T, min_cnt, max_cnt>::OutScalar() );
try{ try{
GenericConvert(out.back(),*(*inp)[i], db); GenericConvert(out.back(),(*inp)[i], db);
} }
catch(const TypeError& t) { catch(const TypeError& t) {
throw TypeError(t.what() +std::string(" of aggregate")); throw TypeError(t.what() +std::string(" of aggregate"));
@ -799,8 +789,8 @@ namespace STEP {
template <typename T> template <typename T>
struct InternGenericConvert< Lazy<T> > { struct InternGenericConvert< Lazy<T> > {
void operator()(Lazy<T>& out, const EXPRESS::DataType& in_base, const STEP::DB& db) { void operator()(Lazy<T>& out, boost::shared_ptr< const EXPRESS::DataType >& in_base, const STEP::DB& db) {
const EXPRESS::ENTITY* in = dynamic_cast<const EXPRESS::ENTITY*>(&in_base); const EXPRESS::ENTITY* in = dynamic_cast<const EXPRESS::ENTITY*>(in_base.get());
if (!in) { if (!in) {
throw TypeError("type error reading entity"); throw TypeError("type error reading entity");
} }
@ -809,12 +799,12 @@ namespace STEP {
}; };
template <typename T1> template <typename T1>
inline void GenericConvert(T1& a, const EXPRESS::DataType& b, const STEP::DB& db) { inline void GenericConvert(T1& a, boost::shared_ptr< const EXPRESS::DataType >& b, const STEP::DB& db) {
return InternGenericConvert<T1>()(a,b,db); return InternGenericConvert<T1>()(a,b,db);
} }
template <typename T1,uint64_t N1, uint64_t N2> 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) { inline void GenericConvert(ListOf<T1,N1,N2>& a, boost::shared_ptr< const EXPRESS::DataType >& b, const STEP::DB& db) {
return InternGenericConvertList<T1,N1,N2>()(a,b,db); return InternGenericConvertList<T1,N1,N2>()(a,b,db);
} }

View File

@ -136,7 +136,7 @@ STEP::DB* STEP::ReadFileHeader(boost::shared_ptr<IOStream> stream)
// two nested lists. // two nested lists.
const EXPRESS::LIST* list = dynamic_cast<const EXPRESS::LIST*>(schema.get()); const EXPRESS::LIST* list = dynamic_cast<const EXPRESS::LIST*>(schema.get());
if (list && list->GetSize()) { if (list && list->GetSize()) {
list = dynamic_cast<const EXPRESS::LIST*>( (*list)[0] ); list = dynamic_cast<const EXPRESS::LIST*>( (*list)[0].get() );
if (!list) { if (!list) {
throw STEP::SyntaxError("expected FILE_SCHEMA to be a list",line); throw STEP::SyntaxError("expected FILE_SCHEMA to be a list",line);
} }
@ -146,7 +146,7 @@ STEP::DB* STEP::ReadFileHeader(boost::shared_ptr<IOStream> stream)
DefaultLogger::get()->warn(AddLineNumber("multiple schemas currently not supported",line)); DefaultLogger::get()->warn(AddLineNumber("multiple schemas currently not supported",line));
} }
const EXPRESS::STRING* string; const EXPRESS::STRING* string;
if (!list->GetSize() || !(string=dynamic_cast<const EXPRESS::STRING*>( (*list)[0] ))) { if (!list->GetSize() || !(string=dynamic_cast<const EXPRESS::STRING*>( (*list)[0].get() ))) {
throw STEP::SyntaxError("expected FILE_SCHEMA to contain a single string literal",line); throw STEP::SyntaxError("expected FILE_SCHEMA to contain a single string literal",line);
} }
head.fileSchema = *string; head.fileSchema = *string;
@ -390,7 +390,7 @@ const EXPRESS::LIST* EXPRESS::LIST::Parse(const char*& inout,uint64_t line, cons
break; break;
} }
members.push_back( EXPRESS::DataType::Parse(cur,line,schema)); members.push_back( boost::shared_ptr<const EXPRESS::DataType> (EXPRESS::DataType::Parse(cur,line,schema)));
SkipSpaces(cur,&cur); SkipSpaces(cur,&cur);
if (*cur != ',') { if (*cur != ',') {
@ -479,7 +479,7 @@ void STEP::LazyObject::LazyInit() const
// store the original id in the object instance // store the original id in the object instance
obj->SetID(id); obj->SetID(id);
//delete conv_args; delete conv_args;
//conv_args = NULL; conv_args = NULL;
} }

View File

@ -79,7 +79,7 @@ template_converter_prologue_a = '\tsize_t base = GenericFill(db,params,static_ca
template_converter_prologue_b = '\tsize_t base = 0;\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_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 template_converter_code_per_field = r""" do {{ // convert the '{fieldname}' argument
const DataType* arg = params[base++];{handle_unset}{convert} boost::shared_ptr<const DataType> arg = params[base++];{handle_unset}{convert}
}} while(0); }} while(0);
""" """
template_allow_optional = r""" template_allow_optional = r"""
@ -87,7 +87,7 @@ template_allow_optional = r"""
template_allow_derived = r""" template_allow_derived = r"""
if (dynamic_cast<const ISDERIVED*>(&*arg)) {{ in->ObjectHelper<Assimp::IFC::{type},{argcnt}>::aux_is_derived[{argnum}]=true; break; }}""" if (dynamic_cast<const ISDERIVED*>(&*arg)) {{ in->ObjectHelper<Assimp::IFC::{type},{argcnt}>::aux_is_derived[{argnum}]=true; break; }}"""
template_convert_single = r""" template_convert_single = r"""
try {{ GenericConvert( in->{name}, *arg, db ); break; }} 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}`")); }}""" 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_ommitted = '// this data structure is not used yet, so there is no code generated to fill its members\n'