Toposhape/Part: element methods in ComplexGeoData and TopoShape
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -301,6 +301,28 @@ public:
|
||||
static bool isElementName(const char *subName) {
|
||||
return (subName != nullptr) && (*subName != 0) && findElementName(subName)==subName;
|
||||
}
|
||||
/** Element trace callback
|
||||
*
|
||||
* The callback has the following call signature
|
||||
* (const std::string &name, size_t offset, long encodedTag, long tag) -> bool
|
||||
*
|
||||
* @param name: the current element name.
|
||||
* @param offset: the offset skipping the encoded element name for the next iteration.
|
||||
* @param encodedTag: the tag encoded inside the current element, which is usually the tag
|
||||
* of the previous step in the shape history.
|
||||
* @param tag: the tag of the current shape element.
|
||||
*
|
||||
* @sa traceElement()
|
||||
*/
|
||||
typedef std::function<bool(const MappedName&, int, long, long)> TraceCallback;
|
||||
|
||||
/** Iterate through the history of the give element name with a given callback
|
||||
*
|
||||
* @param name: the input element name
|
||||
* @param cb: trace callback with call signature.
|
||||
* @sa TraceCallback
|
||||
*/
|
||||
void traceElement(const MappedName& name, TraceCallback cb) const;
|
||||
|
||||
/** Flush an internal buffering for element mapping */
|
||||
virtual void flushElementMap() const;
|
||||
|
||||
@@ -4084,6 +4084,7 @@ TopoShape &TopoShape::makeRefine(const TopoShape &shape, const char *op, RefineF
|
||||
return *this;
|
||||
}
|
||||
|
||||
// TODO: Does the toponaming branch version of this method need to be here?
|
||||
bool TopoShape::findPlane(gp_Pln &pln, double tol) const {
|
||||
if(_Shape.IsNull())
|
||||
return false;
|
||||
|
||||
@@ -5003,4 +5003,25 @@ bool TopoShape::isSame(const Data::ComplexGeoData &_other) const
|
||||
&& _Shape.IsEqual(other._Shape);
|
||||
}
|
||||
|
||||
void TopoShape::cacheRelatedElements(const Data::MappedName &name,
|
||||
bool sameType,
|
||||
const QVector<Data::MappedElement> & names) const
|
||||
{
|
||||
INIT_SHAPE_CACHE();
|
||||
_Cache->insertRelation(ShapeRelationKey(name,sameType), names);
|
||||
}
|
||||
|
||||
bool TopoShape::getRelatedElementsCached(const Data::MappedName &name,
|
||||
bool sameType,
|
||||
QVector<Data::MappedElement> &names) const
|
||||
{
|
||||
if(!_Cache)
|
||||
return false;
|
||||
auto it = _Cache->relations.find(ShapeRelationKey(name,sameType));
|
||||
if(it == _Cache->relations.end())
|
||||
return false;
|
||||
names = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Part
|
||||
|
||||
Reference in New Issue
Block a user