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.
This commit is contained in:
Zheng, Lei
2024-01-06 21:09:45 -06:00
committed by Yorik van Havre
parent 0004597e0a
commit c59bced261
2 changed files with 236 additions and 1 deletions

View File

@@ -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<TopoShape> &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<TopoShape> &shapes, const char *op=nullptr, bool force=true);
friend class TopoShapeCache;
private:

View File

@@ -22,8 +22,12 @@
* *
***************************************************************************/
#include <BRep_Tool.hxx>
#include "PreCompiled.h"
#ifndef _PreComp_
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#endif
#include "TopoShape.h"
#include "TopoShapeCache.h"
@@ -196,4 +200,212 @@ std::vector<TopoDS_Shape> 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<TopAbs_ShapeEnum, 3> 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<TopoShape> &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<Data::ElementMap::MappedChildElements> children;
children.reserve(count*3);
TopAbs_ShapeEnum types[] = {TopAbs_VERTEX, TopAbs_EDGE, TopAbs_FACE};
for (unsigned i=0; i<sizeof(types)/sizeof(types[0]); ++i) {
int offset = 0;
for (auto & s : shapes) {
if (s.isNull())
continue;
int count = s.countSubShapes(types[i]);
if (!count)
continue;
children.emplace_back();
auto & child = children.back();
child.indexedName = Data::IndexedName::fromConst(shapeName(types[i]).c_str(), 1);
child.offset = offset;
offset += count;
child.count = count;
child.elementMap = s.elementMap();
child.tag = s.Tag;
if (op)
child.postfix = op;
}
}
elementMap()->addChildElements(Tag, children); // Replaces the original line below
//setMappedChildElements(children);
return;
}
}
for(auto &shape : shapes)
mapSubElement(shape,op);
}
TopoShape &TopoShape::makeElementCompound(const std::vector<TopoShape> &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