From c59bced261f252e7ecec3380a109866a173dba56 Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Sat, 6 Jan 2024 21:09:45 -0600 Subject: [PATCH] Part/Toponaming: Add original code for makECompound Renamed to makeElementCompound and modified as little as possible to get it to compile in the new framework. All required auxilliary methods are also brought in. --- src/Mod/Part/App/TopoShape.h | 23 +++ src/Mod/Part/App/TopoShapeExpansion.cpp | 214 +++++++++++++++++++++++- 2 files changed, 236 insertions(+), 1 deletion(-) diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index ca96b028f9..13fe666184 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -606,6 +606,29 @@ public: // double tol=1e-7, double atol=1e-12) const; //@} + void copyElementMap(const TopoShape &other, const char *op=nullptr); + bool canMapElement(const TopoShape &other) const; + void mapSubElement(const TopoShape &other,const char *op=nullptr, bool forceHasher=false); + void mapSubElement(const std::vector &shapes, const char *op); + bool hasPendingElementMap() const; + + + /** Make a compound shape + * + * @param shapes: input shapes + * @param op: optional string to be encoded into topo naming for indicating + * the operation + * @param force: if true and there is only one input shape, then return + * that shape instead. If false, then always return a + * compound, even if there is no input shape. + * + * @return The original content of this TopoShape is discarded and replaced + * with the new shape. The function returns the TopoShape itself as + * a reference so that multiple operations can be carried out for + * the same shape in the same line of code. + */ + TopoShape &makeElementCompound(const std::vector &shapes, const char *op=nullptr, bool force=true); + friend class TopoShapeCache; private: diff --git a/src/Mod/Part/App/TopoShapeExpansion.cpp b/src/Mod/Part/App/TopoShapeExpansion.cpp index 09b90fe98f..e26a6a43e8 100644 --- a/src/Mod/Part/App/TopoShapeExpansion.cpp +++ b/src/Mod/Part/App/TopoShapeExpansion.cpp @@ -22,8 +22,12 @@ * * ***************************************************************************/ -#include + #include "PreCompiled.h" +#ifndef _PreComp_ +#include +#include +#endif #include "TopoShape.h" #include "TopoShapeCache.h" @@ -196,4 +200,212 @@ std::vector TopoShape::findAncestorsShapes(const TopoDS_Shape& sub return shapes; } +#define _HANDLE_NULL_SHAPE(_msg,_throw) do {\ + if(_throw) {\ + FC_THROWM(NullShapeException,_msg);\ + }\ + FC_WARN(_msg);\ +}while(0) + +#define HANDLE_NULL_SHAPE _HANDLE_NULL_SHAPE("Null shape",true) +#define HANDLE_NULL_INPUT _HANDLE_NULL_SHAPE("Null input shape",true) +#define WARN_NULL_INPUT _HANDLE_NULL_SHAPE("Null input shape",false) + +bool TopoShape::hasPendingElementMap() const +{ + return !elementMap(false) + && this->_cache + && (this->_parentCache || this->_cache->cachedElementMap); +} + +bool TopoShape::canMapElement(const TopoShape &other) const { + if(isNull() || other.isNull() || this == &other || other.Tag == -1 || Tag == -1) + return false; + if(!other.Tag + && !other.elementMap(false) + && !other.hasPendingElementMap()) + return false; + initCache(); + other.initCache(); + _cache->relations.clear(); + return true; +} + +void TopoShape::mapSubElement(const TopoShape &other, const char *op, bool forceHasher) { +#ifdef FC_NO_ELEMENT_MAP + return; +#endif + + if(!canMapElement(other)) + return; + + if (!getElementMapSize(false) && this->_Shape.IsPartner(other._Shape)) { + if (!this->Hasher) + this->Hasher = other.Hasher; + copyElementMap(other, op); + return; + } + + bool warned = false; + static const std::array types = {TopAbs_VERTEX, TopAbs_EDGE, TopAbs_FACE}; + + auto checkHasher = [this](const TopoShape &other) { + if(Hasher) { + if(other.Hasher!=Hasher) { + if(!getElementMapSize(false)) { + if(FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + FC_WARN("hasher mismatch"); + }else { + // FC_THROWM(Base::RuntimeError, "hasher mismatch"); + FC_ERR("hasher mismatch"); + } + Hasher = other.Hasher; + } + }else + Hasher = other.Hasher; + }; + + for(auto type : types) { + auto &shapeMap = _cache->getAncestry(type); + auto &otherMap = other._cache->getAncestry(type); + if(!shapeMap.count() || !otherMap.count()) + continue; + if(!forceHasher && other.Hasher) { + forceHasher = true; + checkHasher(other); + } + const char *shapetype = shapeName(type).c_str(); + std::ostringstream ss; + + bool forward; + int count; + if(otherMap.count()<=shapeMap.count()) { + forward = true; + count = otherMap.count(); + }else{ + forward = false; + count = shapeMap.count(); + } + for(int k=1;k<=count;++k) { + int i,idx; + if(forward) { + i = k; + idx = shapeMap.find(_Shape,otherMap.find(other._Shape,k)); + if(!idx) continue; + } else { + idx = k; + i = otherMap.find(other._Shape,shapeMap.find(_Shape,k)); + if(!i) continue; + } + Data::IndexedName element = Data::IndexedName::fromConst(shapetype, idx); + for(auto &v : other.getElementMappedNames( + Data::IndexedName::fromConst(shapetype,i),true)) + { + auto &name = v.first; + auto &sids = v.second; + if(sids.size()) { + if (!Hasher) + Hasher = sids[0].getHasher(); + else if (!sids[0].isFromSameHasher(Hasher)) { + if (!warned) { + warned = true; + FC_WARN("hasher mismatch"); + } + sids.clear(); + } + } + ss.str(""); + elementMap()->encodeElementName(shapetype[0],name,ss,&sids,Tag,op,other.Tag); + elementMap()->setElementName(element,name,Tag, &sids); + } + } + } +} + +void TopoShape::mapSubElement(const std::vector &shapes, const char *op) { +#ifdef FC_NO_ELEMENT_MAP + return; +#endif + + if (shapes.empty()) + return; + + if (shapeType(true) == TopAbs_COMPOUND) { + int count = 0; + for (auto & s : shapes) { + if (s.isNull()) + continue; + if (!getSubShape(TopAbs_SHAPE, ++count, true).IsPartner(s._Shape)) { + count = 0; + break; + } + } + if (count) { + std::vector children; + children.reserve(count*3); + TopAbs_ShapeEnum types[] = {TopAbs_VERTEX, TopAbs_EDGE, TopAbs_FACE}; + for (unsigned i=0; iaddChildElements(Tag, children); // Replaces the original line below + //setMappedChildElements(children); + return; + } + } + + for(auto &shape : shapes) + mapSubElement(shape,op); +} + +TopoShape &TopoShape::makeElementCompound(const std::vector &shapes, const char *op, bool force) +{ + if(!force && shapes.size()==1) { + *this = shapes[0]; + return *this; + } + + BRep_Builder builder; + TopoDS_Compound comp; + builder.MakeCompound(comp); + + if(shapes.empty()) { + setShape(comp); + return *this; + } + + int count = 0; + for(auto &s : shapes) { + if(s.isNull()) { + WARN_NULL_INPUT; + continue; + } + builder.Add(comp,s.getShape()); + ++count; + } + if(!count) + HANDLE_NULL_SHAPE; + setShape(comp); + initCache(); + + mapSubElement(shapes,op); + return *this; +} + } // namespace Part