Part/Toponaming: Clang-tidy cleanup of TopoShapeCache
Part/Toponaming: Move implementions to cpp file Part/Toponaming: Automated code cleanup Part/Toponaming: Address boolean blindess with HistoryTraceType Part/Toponaming: More linter cleanup Part/Toponaming: Add located and moved methods Part/Toponaming: Moved and Located Part/Toponaming: Add missing methods Part/Toponaming: Add test framework for TopoShapeCache Part/Toponaming: Add documentation provided by realthunder Part/Toponaming: Extend tests for TopoShapeCache Part/Toponaming: Rename getInfo to getAncestry Part/Toponaming: Fix bug with newer OCCT Part/Toponaming: Add final tests and tweak naming Part/Toponaming: Address reviewer comments
This commit is contained in:
committed by
Chris Hennes
parent
4077c55fae
commit
48a857e808
@@ -22,4 +22,234 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#include "TopoShapeCache.h"
|
||||
|
||||
using namespace Part;
|
||||
|
||||
ShapeRelationKey::ShapeRelationKey(Data::MappedName name, HistoryTraceType historyTraceType)
|
||||
: name(std::move(name))
|
||||
, historyTraceType(historyTraceType)
|
||||
{}
|
||||
|
||||
bool ShapeRelationKey::operator<(const ShapeRelationKey& other) const
|
||||
{
|
||||
if (historyTraceType != other.historyTraceType) {
|
||||
return historyTraceType < other.historyTraceType;
|
||||
}
|
||||
return name < other.name;
|
||||
}
|
||||
|
||||
TopoShape TopoShapeCache::Ancestry::_getTopoShape(const TopoShape& parent, int index)
|
||||
{
|
||||
auto& ts = topoShapes[index - 1];
|
||||
if (ts.isNull()) {
|
||||
ts.setShape(shapes.FindKey(index), true);
|
||||
ts.initCache();
|
||||
ts._cache->subLocation = ts._Shape.Location();
|
||||
}
|
||||
|
||||
if (ts._Shape.IsEqual(parent._cache->shape)) {
|
||||
return parent;
|
||||
}
|
||||
|
||||
TopoShape res(ts);
|
||||
res.Tag = parent.Tag;
|
||||
res.Hasher = parent.Hasher;
|
||||
|
||||
if (!parent.getShape().Location().IsIdentity()) {
|
||||
res.setShape(TopoShape::moved(res._Shape, parent.getShape().Location()), false);
|
||||
}
|
||||
|
||||
if (ts._cache->cachedElementMap) {
|
||||
res.resetElementMap(ts._cache->cachedElementMap);
|
||||
}
|
||||
else if (parent._parentCache) {
|
||||
// If no cachedElementMap exists, we use _parentCache for
|
||||
// delayed generation of sub element map so that we don't need
|
||||
// to always generate a full map whenever we return a sub
|
||||
// shape. To simplify the mapping and avoid circular
|
||||
// dependency, we do not chain parent and grandparent.
|
||||
// Instead, we always use the cache from the top parent. And to
|
||||
// make it work, we must accumulate the TopLoc_Location along
|
||||
// the lineage, which is required for OCCT shape mapping to
|
||||
// work.
|
||||
//
|
||||
// Cache::subLocation is shared and only contains the location
|
||||
// in the direct parent shape, while TopoShape::_subLocation is
|
||||
// used to accumulate locations in higher ancestors. We
|
||||
// separate these two to avoid invalidating cache.
|
||||
|
||||
res._subLocation = parent._subLocation * parent._cache->subLocation;
|
||||
res._parentCache = parent._parentCache;
|
||||
}
|
||||
else {
|
||||
res._parentCache = owner->shared_from_this();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void TopoShapeCache::Ancestry::clear()
|
||||
{
|
||||
topoShapes.clear();
|
||||
}
|
||||
|
||||
TopoShape TopoShapeCache::Ancestry::getTopoShape(const TopoShape& parent, int index)
|
||||
{
|
||||
TopoShape res;
|
||||
if (index <= 0 || index > shapes.Extent()) {
|
||||
return res;
|
||||
}
|
||||
topoShapes.resize(shapes.Extent());
|
||||
return _getTopoShape(parent, index);
|
||||
}
|
||||
|
||||
std::vector<TopoShape> TopoShapeCache::Ancestry::getTopoShapes(const TopoShape& parent)
|
||||
{
|
||||
int count = shapes.Extent();
|
||||
std::vector<TopoShape> res;
|
||||
res.reserve(count);
|
||||
topoShapes.resize(count);
|
||||
for (int i = 1; i <= count; ++i) {
|
||||
res.push_back(_getTopoShape(parent, i));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
TopoDS_Shape TopoShapeCache::Ancestry::stripLocation(const TopoDS_Shape& parent,
|
||||
const TopoDS_Shape& child)
|
||||
{
|
||||
if (parent.Location() != owner->location) {
|
||||
owner->location = parent.Location();
|
||||
owner->locationInverse = parent.Location().Inverted();
|
||||
}
|
||||
return TopoShape::located(child, owner->locationInverse * child.Location());
|
||||
}
|
||||
|
||||
int TopoShapeCache::Ancestry::find(const TopoDS_Shape& parent, const TopoDS_Shape& subShape)
|
||||
{
|
||||
if (parent.Location().IsIdentity()) {
|
||||
return shapes.FindIndex(subShape);
|
||||
}
|
||||
return shapes.FindIndex(stripLocation(parent, subShape));
|
||||
}
|
||||
|
||||
TopoDS_Shape TopoShapeCache::Ancestry::find(const TopoDS_Shape& parent, int index)
|
||||
{
|
||||
if (index <= 0 || index > shapes.Extent()) {
|
||||
return {};
|
||||
}
|
||||
if (parent.Location().IsIdentity()) {
|
||||
return shapes.FindKey(index);
|
||||
}
|
||||
return TopoShape::moved(shapes.FindKey(index), parent.Location());
|
||||
}
|
||||
|
||||
int TopoShapeCache::Ancestry::count() const
|
||||
{
|
||||
return shapes.Extent();
|
||||
}
|
||||
|
||||
|
||||
TopoShapeCache::TopoShapeCache(const TopoDS_Shape& tds)
|
||||
: shape(tds.Located(TopLoc_Location()))
|
||||
{}
|
||||
|
||||
void TopoShapeCache::insertRelation(const ShapeRelationKey& key,
|
||||
const QVector<Data::MappedElement>& value)
|
||||
{
|
||||
auto [insertedItr, newKeyInserted] = relations.insert({key, value});
|
||||
if (newKeyInserted) {
|
||||
insertedItr->first.name.compact();
|
||||
}
|
||||
else {
|
||||
insertedItr->second = value;
|
||||
}
|
||||
}
|
||||
|
||||
bool TopoShapeCache::isTouched(const TopoDS_Shape& tds) const
|
||||
{
|
||||
return !this->shape.IsPartner(tds) || this->shape.Orientation() != tds.Orientation();
|
||||
}
|
||||
|
||||
TopoShapeCache::Ancestry& TopoShapeCache::getAncestry(TopAbs_ShapeEnum type)
|
||||
{
|
||||
auto& ancestry = shapeAncestryCache.at(type);
|
||||
if (!ancestry.owner) {
|
||||
ancestry.owner = this;
|
||||
if (!shape.IsNull()) {
|
||||
if (type == TopAbs_SHAPE) {
|
||||
for (TopoDS_Iterator it(shape); it.More(); it.Next()) {
|
||||
ancestry.shapes.Add(it.Value());
|
||||
}
|
||||
}
|
||||
else {
|
||||
TopExp::MapShapes(shape, type, ancestry.shapes);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ancestry;
|
||||
}
|
||||
|
||||
int TopoShapeCache::countShape(TopAbs_ShapeEnum type)
|
||||
{
|
||||
if (shape.IsNull()) {
|
||||
return 0;
|
||||
}
|
||||
return getAncestry(type).count();
|
||||
}
|
||||
|
||||
int TopoShapeCache::findShape(const TopoDS_Shape& parent, const TopoDS_Shape& subShape)
|
||||
{
|
||||
if (shape.IsNull() || subShape.IsNull()) {
|
||||
return 0;
|
||||
}
|
||||
return getAncestry(subShape.ShapeType()).find(parent, subShape);
|
||||
}
|
||||
|
||||
TopoDS_Shape TopoShapeCache::findShape(const TopoDS_Shape& parent, TopAbs_ShapeEnum type, int index)
|
||||
{
|
||||
if (!shape.IsNull()) {
|
||||
return getAncestry(type).find(parent, index);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
TopoDS_Shape TopoShapeCache::findAncestor(const TopoDS_Shape& parent,
|
||||
const TopoDS_Shape& subShape,
|
||||
TopAbs_ShapeEnum type,
|
||||
std::vector<TopoDS_Shape>* ancestors)
|
||||
{
|
||||
TopoDS_Shape nullShape;
|
||||
if (shape.IsNull() || subShape.IsNull() || type == TopAbs_SHAPE) {
|
||||
return nullShape;
|
||||
}
|
||||
|
||||
auto& info = getAncestry(type);
|
||||
|
||||
auto& ancestorInfo = info.ancestors.at(subShape.ShapeType());
|
||||
if (!ancestorInfo.initialized) {
|
||||
ancestorInfo.initialized = true;
|
||||
// ancestorInfo.shapes is the output variable here, storing (and caching) the actual map
|
||||
TopExp::MapShapesAndAncestors(shape, subShape.ShapeType(), type, ancestorInfo.shapes);
|
||||
}
|
||||
int index = parent.Location().IsIdentity()
|
||||
? ancestorInfo.shapes.FindIndex(subShape)
|
||||
: ancestorInfo.shapes.FindIndex(info.stripLocation(parent, subShape));
|
||||
if (index == 0) {
|
||||
return nullShape;
|
||||
}
|
||||
const auto& shapes = ancestorInfo.shapes.FindFromIndex(index);
|
||||
if (shapes.Extent() == 0) {
|
||||
return nullShape;
|
||||
}
|
||||
|
||||
if (ancestors) {
|
||||
ancestors->reserve(ancestors->size() + shapes.Extent());
|
||||
for (TopTools_ListIteratorOfListOfShape it(shapes); it.More(); it.Next()) {
|
||||
ancestors->push_back(TopoShape::moved(it.Value(), parent.Location()));
|
||||
}
|
||||
}
|
||||
return TopoShape::moved(shapes.First(), parent.Location());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user