- Ifc: prevent infinite recursion due to cyclic back references which the new STEP backref tracker might produce.
parent
03b8431d54
commit
10f8eda497
|
@ -513,7 +513,7 @@ struct RateRepresentationPredicate {
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// give strong preference to extruded geometry
|
// give strong preference to extruded geometry.
|
||||||
if (r == "SweptSolid") {
|
if (r == "SweptSolid") {
|
||||||
return -10;
|
return -10;
|
||||||
}
|
}
|
||||||
|
@ -672,6 +672,8 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
|
||||||
nd->mName.Set(el.GetClassName()+"_"+(el.Name?el.Name.Get():"Unnamed")+"_"+el.GlobalId);
|
nd->mName.Set(el.GetClassName()+"_"+(el.Name?el.Name.Get():"Unnamed")+"_"+el.GlobalId);
|
||||||
nd->mParent = parent;
|
nd->mParent = parent;
|
||||||
|
|
||||||
|
conv.already_processed.insert(el.GetID());
|
||||||
|
|
||||||
// check for node metadata
|
// check for node metadata
|
||||||
STEP::DB::RefMapRange children = refs.equal_range(el.GetID());
|
STEP::DB::RefMapRange children = refs.equal_range(el.GetID());
|
||||||
if (children.first!=refs.end()) {
|
if (children.first!=refs.end()) {
|
||||||
|
@ -724,15 +726,24 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
|
||||||
STEP::DB::RefMapRange range = refs.equal_range(el.GetID());
|
STEP::DB::RefMapRange range = refs.equal_range(el.GetID());
|
||||||
|
|
||||||
for(STEP::DB::RefMapRange range2 = range; range2.first != range.second; ++range2.first) {
|
for(STEP::DB::RefMapRange range2 = range; range2.first != range.second; ++range2.first) {
|
||||||
|
// skip over meshes that have already been processed before. This is strictly necessary
|
||||||
|
// because the reverse indices also include references contained in argument lists and
|
||||||
|
// therefore every element has a back-reference hold by its parent.
|
||||||
|
if (conv.already_processed.find((*range2.first).second) != conv.already_processed.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const STEP::LazyObject& obj = conv.db.MustGetObject((*range2.first).second);
|
const STEP::LazyObject& obj = conv.db.MustGetObject((*range2.first).second);
|
||||||
|
|
||||||
// handle regularly-contained elements
|
// handle regularly-contained elements
|
||||||
if(const IfcRelContainedInSpatialStructure* const cont = obj->ToPtr<IfcRelContainedInSpatialStructure>()) {
|
if(const IfcRelContainedInSpatialStructure* const cont = obj->ToPtr<IfcRelContainedInSpatialStructure>()) {
|
||||||
|
if(cont->RelatingStructure->GetID() != el.GetID()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
BOOST_FOREACH(const IfcProduct& pro, cont->RelatedElements) {
|
BOOST_FOREACH(const IfcProduct& pro, cont->RelatedElements) {
|
||||||
if(const IfcOpeningElement* const open = pro.ToPtr<IfcOpeningElement>()) {
|
if(const IfcOpeningElement* const open = pro.ToPtr<IfcOpeningElement>()) {
|
||||||
// IfcOpeningElement is handled below. Sadly we can't use it here as is:
|
// IfcOpeningElement is handled below. Sadly we can't use it here as is:
|
||||||
// The docs say that opening elements are USUALLY attached to building storeys
|
// The docs say that opening elements are USUALLY attached to building storey,
|
||||||
// but we want them for the building elements to which they belong to.
|
// but we want them for the building elements to which they belong.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -783,7 +794,14 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
|
||||||
}
|
}
|
||||||
|
|
||||||
for(;range.first != range.second; ++range.first) {
|
for(;range.first != range.second; ++range.first) {
|
||||||
|
// see note in loop above
|
||||||
|
if (conv.already_processed.find((*range.first).second) != conv.already_processed.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if(const IfcRelAggregates* const aggr = conv.db.GetObject((*range.first).second)->ToPtr<IfcRelAggregates>()) {
|
if(const IfcRelAggregates* const aggr = conv.db.GetObject((*range.first).second)->ToPtr<IfcRelAggregates>()) {
|
||||||
|
if(aggr->RelatingObject->GetID() != el.GetID()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// move aggregate elements to a separate node since they are semantically different than elements that are just 'contained'
|
// move aggregate elements to a separate node since they are semantically different than elements that are just 'contained'
|
||||||
std::auto_ptr<aiNode> nd_aggr(new aiNode());
|
std::auto_ptr<aiNode> nd_aggr(new aiNode());
|
||||||
|
@ -829,6 +847,8 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ai_assert(conv.already_processed.find(el.GetID()) != conv.already_processed.end());
|
||||||
|
conv.already_processed.erase(conv.already_processed.find(el.GetID()));
|
||||||
return nd.release();
|
return nd.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -208,6 +208,8 @@ struct ConversionData
|
||||||
// for later processing by a parent, which is a wall.
|
// for later processing by a parent, which is a wall.
|
||||||
std::vector<TempOpening>* apply_openings;
|
std::vector<TempOpening>* apply_openings;
|
||||||
std::vector<TempOpening>* collect_openings;
|
std::vector<TempOpening>* collect_openings;
|
||||||
|
|
||||||
|
std::set<uint64_t> already_processed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue