You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AppFlow/FITK_Component/FITKGeoCompOCC/FITKOCCVirtualTopoCreator.cpp

284 lines
11 KiB
C++

#include "FITKOCCVirtualTopoCreator.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKVirtualTopoManager.h"
#include "FITK_Kernel/FITKAppFramework/FITKMessage.h"
#include "FITK_Kernel/FITKCore/FITKThreadPool.h"
#include "FITK_Kernel/FITKCore/FITKThreadTaskGroup.h"
#include <TopExp_Explorer.hxx>
#include <QHash>
#include <QList>
#include <TopAbs_ShapeEnum.hxx>
#include <TopoDS_Shape.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <BRepCheck_Analyzer.hxx>
#include <TopExp.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Vertex.hxx>
#include <BRep_Tool.hxx>
#include <TopoDS_Iterator.hxx>
#include <QDateTime>
#include <QDebug>
namespace OCC
{
//几何类型映射
QHash<TopAbs_ShapeEnum, Interface::FITKGeoEnum::VTopoShapeType> OCCShapeEnumHash = {
{TopAbs_COMPOUND, Interface::FITKGeoEnum::VSAssembly},
{TopAbs_SOLID, Interface::FITKGeoEnum::VSSolid},
{TopAbs_SHELL, Interface::FITKGeoEnum::VSShell},
{TopAbs_FACE, Interface::FITKGeoEnum::VSFace},
{TopAbs_WIRE, Interface::FITKGeoEnum::VSWire},
{TopAbs_EDGE, Interface::FITKGeoEnum::VSEdge},
{TopAbs_VERTEX, Interface::FITKGeoEnum::VSPoint},
};
//支持的OCC类型需要注意层次顺序
QList<TopAbs_ShapeEnum> OCCShapeEnumList = {
TopAbs_COMPOUND,TopAbs_SOLID,TopAbs_SHELL ,TopAbs_FACE,TopAbs_WIRE, TopAbs_EDGE, TopAbs_VERTEX };
FITKOCCTopoShape::FITKOCCTopoShape(const TopoDS_Shape & shape)
{
_shape = new TopoDS_Shape;
*_shape = shape;
}
bool FITKOCCTopoShape::isSameShape(void* s)
{
TopoDS_Shape* shape = static_cast<TopoDS_Shape*>(s);
return shape->IsSame(*_shape);
}
const TopoDS_Shape& FITKOCCTopoShape::getTopoShape() const
{
return *_shape;
}
FITKOCCVirtualTopoCreator::FITKOCCVirtualTopoCreator(const TopoDS_Shape& shape, Interface::FITKVirtualTopoManager* topo, const QString& model, bool& r)
:_shape(shape), _topoMgr(topo), _modelName(model), _runLabel(r)
{
_runLabel = true;
}
FITKOCCVirtualTopoCreator::~FITKOCCVirtualTopoCreator()
{
_runLabel = false;
}
void FITKOCCVirtualTopoCreator::run()
{
// Core::FITKThreadPool::getInstance()->wait();
if (_topoMgr == nullptr) return;
if (_topoMgr->getAllShapeVirtualTopoCount() == 0) return;
// AppFrame::FITKMessageNormal(QString("%1 building virtual topo...").arg(_modelName));
this->buildTopoTree(_shape, _topoMgr, _topoMgr->getRootObj());
// AppFrame::FITKMessageNormal(QString("%1 virtual topo built !").arg(_modelName));
// qDebug() << "topo build: " << QDateTime::currentDateTime().toString("hh:mm:ss:zzz");
}
void FITKOCCVirtualTopoCreator::createOCCTopos()
{
// qDebug() << "build topo: " << QDateTime::currentDateTime().toString("hh:mm:ss:zzz");
if (_topoMgr == nullptr) return;
//顶层形状类型
TopAbs_ShapeEnum shapeEnum = _shape.ShapeType();
int index = OCCShapeEnumList.indexOf(shapeEnum);
if (index < 0)
{
shapeEnum = TopAbs_COMPOUND;
index = 0;
}
//顶层节点
Interface::FITKGeoEnum::VTopoShapeType vts = OCCShapeEnumHash.value(shapeEnum);
Interface::FITKAbsVirtualTopo* parent = new Interface::FITKAbsVirtualTopo;
parent->setShapeType(vts);
parent->setShape(new FITKOCCTopoShape(_shape));
_topoMgr->setRootObj(parent);
_topoMgr->appendVirtualTopoObj(parent);
parent->setIndexLabel(0);
int hashInt = _shape.HashCode(std::numeric_limits<int>::max());
// _virtualTopoHash.insert(hashInt, parent);
_virtualTopoHash[vts][hashInt] = parent;
Core::FITKThreadTaskGroup g;
while (++index < OCCShapeEnumList.size())
{
TopAbs_ShapeEnum cshapeEnum = OCCShapeEnumList[index];
if (!OCCShapeEnumHash.contains(cshapeEnum))
{
//index++;
continue;
}
Interface::FITKGeoEnum::VTopoShapeType cvts = OCCShapeEnumHash.value(cshapeEnum);
// QHash<int, Interface::FITKAbsVirtualTopo*>& s = _virtualTopoHash[cvts];
FITKOCCVirtualTopoMapper* m = new FITKOCCVirtualTopoMapper(_shape, _topoMgr, _virtualTopoHash, index);
g.appendThreadTask(m);
//index++;
}
g.push2ThreadPool();
g.wait();
qDebug() << "create topo Obj: " << QDateTime::currentDateTime().toString("hh:mm:ss:zzz");
}
void FITKOCCVirtualTopoCreator::buildTopoTree(const TopoDS_Shape& shape,
Interface::FITKVirtualTopoManager* topomgr, Interface::FITKAbsVirtualTopo* parent)
{
//顶层形状类型
TopAbs_ShapeEnum shapeEnum = shape.ShapeType();
int index = OCCShapeEnumList.indexOf(shapeEnum);
if (index < 0)
{
shapeEnum = TopAbs_COMPOUND;
index = 0;
}
//遍历当前层级的字形状
while (++index < OCCShapeEnumList.size())
{
TopAbs_ShapeEnum cshapeEnum = OCCShapeEnumList[index];
Interface::FITKGeoEnum::VTopoShapeType cvts = OCCShapeEnumHash.value(cshapeEnum);
// 特殊处理复合对象。 Added by ChengHaotian 2024/09/19
//@{
if (shapeEnum == TopAbs_ShapeEnum::TopAbs_COMPOUND)
{
TopoDS_Iterator iter(shape);
for (; iter.More(); iter.Next())
{
const TopoDS_Shape & subShape = iter.Value();
const int sHash = subShape.HashCode(std::numeric_limits<int>::max());
Interface::FITKGeoEnum::VTopoShapeType subCvts = OCCShapeEnumHash.value(subShape.ShapeType());
Interface::FITKAbsVirtualTopo* subtopo = _virtualTopoHash[subCvts][sHash];
if (subtopo == nullptr)
continue;
parent->addSubTopo(subtopo);
if (subCvts == Interface::FITKGeoEnum::VSPoint) continue;
this->buildTopoTree(subShape, topomgr, subtopo);
break;
}
}
//@}
else
{
TopTools_IndexedMapOfShape map;
TopExp::MapShapes(shape, cshapeEnum, map);
const int subShapeCount = map.Extent();
if (subShapeCount < 1) continue;
for (int i = 1; i <= subShapeCount; i++)
{
//当前形状
const TopoDS_Shape& subShape = map.FindKey(i);
const int sHash = subShape.HashCode(std::numeric_limits<int>::max());
Interface::FITKAbsVirtualTopo* subtopo = _virtualTopoHash[cvts][sHash];
//topomgr->getVirtualTopo(&subShape, cvts);
if (subtopo == nullptr)
continue;
parent->addSubTopo(subtopo);
if (cvts == Interface::FITKGeoEnum::VSPoint) continue;
this->buildTopoTree(subShape, topomgr, subtopo);
}
}
break;
}
}
FITKOCCVirtualTopoMapper::FITKOCCVirtualTopoMapper(const TopoDS_Shape& shape, Interface::FITKVirtualTopoManager* topomgr,
QHash<Interface::FITKGeoEnum::VTopoShapeType, QHash<int, Interface::FITKAbsVirtualTopo*>> &topos, int shapeTypeIndex)
:_shape(shape), _topos(topos), _topoMgr(topomgr), _shapeTypeIndex(shapeTypeIndex)
{
TopAbs_ShapeEnum cshapeEnum = OCCShapeEnumList[_shapeTypeIndex];
if (!OCCShapeEnumHash.contains(cshapeEnum)) return;
Interface::FITKGeoEnum::VTopoShapeType cvts = OCCShapeEnumHash.value(cshapeEnum);
// 特殊处理复合对象。 Added by ChengHaotian 2024/09/19
//@{
if (cshapeEnum == TopAbs_ShapeEnum::TopAbs_COMPOUND)
{
TopoDS_Iterator iter(_shape);
for (; iter.More(); iter.Next())
{
_topoList.append(new Interface::FITKAbsVirtualTopo);
}
}
//@}
else
{
TopTools_IndexedMapOfShape map;
TopExp::MapShapes(_shape, cshapeEnum, map);
const int subShapeCount = map.Extent();
if (subShapeCount < 1) return;
for (int i = 1; i <= subShapeCount; ++i)
{
_topoList.append(new Interface::FITKAbsVirtualTopo);
}
}
}
void FITKOCCVirtualTopoMapper::run()
{
TopAbs_ShapeEnum cshapeEnum = OCCShapeEnumList[_shapeTypeIndex];
if (!OCCShapeEnumHash.contains(cshapeEnum)) return;
Interface::FITKGeoEnum::VTopoShapeType cvts = OCCShapeEnumHash.value(cshapeEnum);
// 特殊处理复合对象。 Added by ChengHaotian 2024/09/19
//@{
if (cshapeEnum == TopAbs_ShapeEnum::TopAbs_COMPOUND)
{
QList<Interface::FITKAbsVirtualTopo*> topoObjs;
int iShape = 0;
TopoDS_Iterator iter(_shape);
for (; iter.More(); iter.Next())
{
const TopoDS_Shape & subShape = iter.Value();
Interface::FITKGeoEnum::VTopoShapeType subCvts = OCCShapeEnumHash.value(subShape.ShapeType());
Interface::FITKAbsVirtualTopo* vTopo = _topoList[iShape];
vTopo->setShapeType(subCvts);
vTopo->setShape(new FITKOCCTopoShape(subShape));
vTopo->setIndexLabel(iShape);
topoObjs.append(vTopo);
int hashInt = subShape.HashCode(std::numeric_limits<int>::max());
_topos[subCvts][hashInt] = vTopo;
iShape++;
}
_topoMgr->appendVirtualTopoObjs(topoObjs);
}
//@}
else
{
TopTools_IndexedMapOfShape map;
TopExp::MapShapes(_shape, cshapeEnum, map);
const int subShapeCount = map.Extent();
if (subShapeCount < 1) return;
QList<Core::FITKAbstractDataObject*> topoObjs;
for (int i = 1; i <= subShapeCount; i++)
{
//当前形状
const TopoDS_Shape & subShape = map.FindKey(i);
Interface::FITKAbsVirtualTopo* subtopo = _topoList.at(i - 1);//new Interface::FITKAbsVirtualTopo;
subtopo->setShapeType(cvts);
subtopo->setShape(new FITKOCCTopoShape(subShape));
subtopo->setIndexLabel(i - 1);
topoObjs.append(subtopo);
int hashInt = subShape.HashCode(std::numeric_limits<int>::max());
// _virtualTopoHash.insert(hashInt, subtopo);
_topos[cvts][hashInt] = subtopo;
}
_topoMgr->appendVirtualTopoObjs(cvts, topoObjs);
}
}
}