Toposhape/Part: element methods in ComplexGeoData and TopoShape

This commit is contained in:
Zheng, Lei
2024-02-27 15:33:21 -05:00
committed by bgbsww
parent cd0d58cfe9
commit 5e532494ca
4 changed files with 120 additions and 0 deletions

View File

@@ -637,6 +637,82 @@ unsigned int ComplexGeoData::getMemSize() const
return 0;
}
void ComplexGeoData::traceElement(const MappedName &name, TraceCallback cb) const
{
long tag = this->Tag, encodedTag = 0;
int len = 0;
auto pos = findTagInElementName(name,&encodedTag,&len,nullptr,nullptr,true);
if(cb(name, len, encodedTag, tag) || pos < 0)
return;
if (name.startsWith(externalTagPostfix(), len))
return;
std::set<long> tagSet;
std::vector<MappedName> names;
if (tag)
tagSet.insert(std::abs(tag));
if (encodedTag)
tagSet.insert(std::abs(encodedTag));
names.push_back(name);
tag = encodedTag;
MappedName tmp;
bool first = true;
// TODO: element tracing without object is inheriently unsafe, because of
// possible external linking object which means the element may be encoded
// using external string table. Looking up the wrong table may accidentally
// cause circular mapping, and is actually quite easy to reproduce. See
//
// https://github.com/realthunder/FreeCAD_assembly3/issues/968
//
// A random depth limit is set here to not waste time. 'tagSet' above is
// also used for early detection of 'recursive' mapping.
for (int i=0; i<50; ++i) {
if(!len || len>pos)
return;
if(first) {
first = false;
size_t offset = 0;
if(name.startsWith(elementMapPrefix()))
offset = elementMapPrefix().size();
tmp = MappedName(name, offset, len);
}else
tmp = MappedName(tmp, 0, len);
tmp = dehashElementName(tmp);
names.push_back(tmp);
encodedTag = 0;
pos = findTagInElementName(tmp,&encodedTag,&len,nullptr,nullptr,true);
if (pos >= 0 && tmp.startsWith(externalTagPostfix(), len))
break;
if (encodedTag && tag != std::abs(encodedTag)
&& !tagSet.insert(std::abs(encodedTag)).second) {
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) {
FC_WARN("circular element mapping");
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_TRACE)) {
auto doc = App::GetApplication().getActiveDocument();
if (doc) {
auto obj = doc->getObjectByID(this->Tag);
if (obj)
FC_LOG("\t" << obj->getFullName() << obj->getFullName() << "." << getIndexedName(name));
}
for (auto &name : names)
FC_ERR("\t" << name);
}
}
break;
}
if(cb(tmp, len, encodedTag, tag) || pos < 0)
return;
tag = encodedTag;
}
}
void ComplexGeoData::setMappedChildElements(const std::vector<Data::ElementMap::MappedChildElements> & children)
{