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.
759 lines
30 KiB
C++
759 lines
30 KiB
C++
#include "FITKOCCModelSolid.h"
|
|
#include <gp_Pnt.hxx>
|
|
#include <gp_Dir.hxx>
|
|
#include <TopoDS.hxx>
|
|
#include <BRepBuilderAPI_MakeWire.hxx>
|
|
#include <BRepPrimAPI_MakeRevol.hxx>
|
|
#include <BRepPrimAPI_MakePrism.hxx>
|
|
#include <BRepOffset_MakeOffset.hxx>
|
|
#include <BRepOffsetAPI_MakePipe.hxx>
|
|
#include <BRepBuilderAPI_MakeShell.hxx>
|
|
#include <BRepBuilderAPI_MakeSolid.hxx>
|
|
#include <BRepBuilderAPI_Sewing.hxx>
|
|
#include <TopoDS_Iterator.hxx>
|
|
#include <TopExp_Explorer.hxx>
|
|
#include <BRepBuilderAPI_MakeFace.hxx>
|
|
#include <Precision.hxx>
|
|
#include <BRepBndLib.hxx>
|
|
#include <BRepOffsetAPI_ThruSections.hxx>
|
|
|
|
#include <TopoDS_Shape.hxx>
|
|
#include <TopoDS_Edge.hxx>
|
|
#include <TopoDS_Wire.hxx>
|
|
|
|
#include <FITK_Interface/FITKInterfaceGeometry/FITKGeoEnum.h>
|
|
#include <FITK_Interface/FITKInterfaceGeometry/FITKVirtualTopoManager.h>
|
|
#include "FITKOCCVirtualTopoCreator.h"
|
|
|
|
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
|
|
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
|
|
#include "FITK_Interface/FITKInterfaceGeometry/FITKGeoCommandList.h"
|
|
#include "FITK_Interface/FITKInterfaceGeometry/FITKGeoInterfaceFactory.h"
|
|
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoModelSurface.h"
|
|
|
|
#include <FITKOCCModelCurve.h>
|
|
|
|
namespace {
|
|
struct CWire {
|
|
Bnd_Box Bound;
|
|
BRepBuilderAPI_MakeWire MakeWire{};
|
|
gp_Pnt Start{};
|
|
gp_Pnt End{};
|
|
bool isNull() { return MakeWire.Edge().IsNull(); }
|
|
bool isClosed() { return MakeWire.Shape().Closed(); }
|
|
};
|
|
}
|
|
|
|
namespace OCC
|
|
{
|
|
FITKOCCModelClosedSurfaceSolid::FITKOCCModelClosedSurfaceSolid() : OCCShapeAgent(this)
|
|
{
|
|
_shapeAgent = _occShapeAgent;
|
|
}
|
|
bool FITKOCCModelClosedSurfaceSolid::update()
|
|
{
|
|
if (m_Faces.isEmpty()) return false;
|
|
|
|
auto geoCmdList = FITKGLODATA->getGeometryData<Interface::FITKGeoCommandList>();
|
|
|
|
BRepBuilderAPI_Sewing sewing;
|
|
|
|
for (int i = 0; i < m_Faces.size(); ++i) {
|
|
auto face = m_Faces.at(i);
|
|
if (face.isNull()) continue;
|
|
|
|
auto cmd = geoCmdList->getDataByID(face.CmdId);
|
|
if (cmd == nullptr)
|
|
{
|
|
printLog(tr("Failed to get geometry command."), 3);
|
|
return false;
|
|
}
|
|
auto vshape = cmd->getShapeT<FITKOCCTopoShape>(Interface::FITKGeoEnum::VTopoShapeType::VSFace, face.VirtualTopoId);
|
|
if (vshape == nullptr)
|
|
{
|
|
printLog(tr("Failed to get face from virtual topo."), 3);
|
|
return false;
|
|
}
|
|
auto topoShape = vshape->getTopoShape();
|
|
if (topoShape.ShapeType() == TopAbs_ShapeEnum::TopAbs_FACE) {
|
|
TopoDS_Face f = TopoDS::Face(topoShape);
|
|
if (f.IsNull()) continue;
|
|
if (f.Orientation() == TopAbs_Orientation::TopAbs_REVERSED) {
|
|
f.Reverse();
|
|
}
|
|
sewing.Add(f);
|
|
}
|
|
else {
|
|
printLog(tr("Error topo shape type for make wire."), 3);
|
|
return false;
|
|
}
|
|
}
|
|
sewing.Perform();
|
|
|
|
auto type = sewing.SewedShape().ShapeType();
|
|
|
|
/*if (type == TopAbs_COMPOUND)
|
|
{
|
|
TopoDS_Builder aShellBuilder;
|
|
TopoDS_Shell aShell;
|
|
|
|
aShellBuilder.MakeShell(aShell);
|
|
|
|
int faceCount = 0;
|
|
int edgeCount = 0;
|
|
|
|
for (TopoDS_Iterator anExp(sewing.SewedShape()); anExp.More(); anExp.Next())
|
|
{
|
|
const TopoDS_Shape &curShape1 = anExp.Value();
|
|
TopAbs_ShapeEnum type1 = curShape1.ShapeType();
|
|
|
|
if (type1 == TopAbs_SHELL)
|
|
{
|
|
for (TopExp_Explorer anExp(curShape1, TopAbs_FACE); anExp.More(); anExp.Next())
|
|
{
|
|
const TopoDS_Shape &curShape2 = anExp.Current();
|
|
aShellBuilder.Add(aShell, curShape2);
|
|
faceCount++;
|
|
}
|
|
}
|
|
}
|
|
}*/
|
|
|
|
if (type != TopAbs_SHELL)
|
|
{
|
|
printLog(tr("Error topo shape type for make wire."), 3);
|
|
return false;
|
|
}
|
|
try {
|
|
TopoDS_Shell shell = TopoDS::Shell(sewing.SewedShape());
|
|
if (shell.IsNull() || !shell.Closed()) {
|
|
printLog(tr("Must be closed shell."), 3);
|
|
return false;
|
|
}
|
|
BRepBuilderAPI_MakeSolid solid(shell);
|
|
|
|
if (!solid.IsDone()) {
|
|
printLog(tr("Error topo shape type for make wire."), 3);
|
|
return false;
|
|
}
|
|
_occShapeAgent->updateShape(solid.Shape());
|
|
}
|
|
catch (...)
|
|
{
|
|
printLog(tr("Failed to make solid!"), 3);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
FITKOCCModelExtrudeSolid::FITKOCCModelExtrudeSolid() : OCCShapeAgent(this)
|
|
{
|
|
_shapeAgent = _occShapeAgent;
|
|
}
|
|
bool FITKOCCModelExtrudeSolid::update()
|
|
{
|
|
|
|
auto geoCmdList = FITKGLODATA->getGeometryData<Interface::FITKGeoCommandList>();
|
|
|
|
auto cmd = geoCmdList->getDataByID(m_SourceSurface.CmdId);
|
|
if (cmd == nullptr) return false;
|
|
|
|
Interface::FITKGeoEnum::VTopoShapeType type = cmd->getGeometryCommandType() == Interface::FITKGeoEnum::FITKGeometryComType::FGTSketch2D ? Interface::FITKGeoEnum::VTopoShapeType::VSAssembly : Interface::FITKGeoEnum::VTopoShapeType::VSFace;
|
|
|
|
auto shape = cmd->getShapeT<FITKOCCTopoShape>(type, m_SourceSurface.VirtualTopoId);
|
|
if (shape == nullptr) return false;
|
|
|
|
auto topoShape = shape->getTopoShape();
|
|
gp_Vec dir(m_Direction[0], m_Direction[1], m_Direction[2]);
|
|
auto mag = dir.Magnitude();
|
|
if (mag <= Precision::Confusion()) {
|
|
printLog(tr("The direction cannot be a zero vector!"), 3);
|
|
return false;
|
|
}
|
|
dir = dir * m_Length / mag;
|
|
|
|
try {
|
|
// 如果是草绘则返回的是线的组合体,需要合并面
|
|
if (topoShape.ShapeType() == TopAbs_ShapeEnum::TopAbs_COMPOUND)
|
|
{
|
|
TopoDS_Compound compound = TopoDS::Compound(topoShape);
|
|
TopExp_Explorer exp;
|
|
|
|
|
|
QList<CWire> wiresList{};
|
|
|
|
// 按封闭曲线分组
|
|
for (exp.Init(compound, TopAbs_EDGE); exp.More(); exp.Next())
|
|
{
|
|
TopoDS_Edge edge = TopoDS::Edge(exp.Current());
|
|
if (edge.IsNull()) continue;
|
|
|
|
Standard_Real first;
|
|
Standard_Real last;
|
|
Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, first, last);
|
|
gp_Pnt start = curve->Value(first);
|
|
gp_Pnt end = curve->Value(last);
|
|
|
|
/* 自成封闭的曲线 */
|
|
/* @{ */
|
|
if (start.Distance(end) < Precision::Confusion()) {
|
|
CWire w;
|
|
w.MakeWire.Add(edge);
|
|
w.Start = start;
|
|
w.End = end;
|
|
wiresList.push_back(w);
|
|
continue;
|
|
}
|
|
/* @} */
|
|
|
|
/* 是否能拼接到已有曲线 */
|
|
/* @{ */
|
|
bool isSep{ true };
|
|
for (auto& wire : wiresList) {
|
|
// 已经闭合的曲线不参与比较
|
|
if (wire.isClosed()) continue;
|
|
if (wire.Start.Distance(start) < Precision::Confusion())
|
|
{
|
|
wire.MakeWire.Add(edge);
|
|
wire.Start = end;
|
|
isSep = false;
|
|
break;
|
|
}
|
|
else if (wire.Start.Distance(end) < Precision::Confusion())
|
|
{
|
|
wire.MakeWire.Add(edge);
|
|
wire.Start = start;
|
|
isSep = false;
|
|
break;
|
|
}
|
|
else if (wire.End.Distance(start) < Precision::Confusion())
|
|
{
|
|
wire.MakeWire.Add(edge);
|
|
wire.End = end;
|
|
isSep = false;
|
|
break;
|
|
}
|
|
else if (wire.End.Distance(end) < Precision::Confusion())
|
|
{
|
|
wire.MakeWire.Add(edge);
|
|
wire.End = start;
|
|
isSep = false;
|
|
break;
|
|
}
|
|
else {
|
|
printLog(QString("wire.Start: [%1, %2, %3]; wire.End: [%4, %5, %6]").arg(wire.Start.X()).arg(wire.Start.Y()).arg(wire.Start.Z()).arg(wire.End.X()).arg(wire.End.Y()).arg(wire.End.Z()), 2);
|
|
printLog(QString("Start: [%1, %2, %3]; End: [%4, %5, %6]").arg(start.X()).arg(start.Y()).arg(start.Z()).arg(end.X()).arg(end.Y()).arg(end.Z()), 2);
|
|
}
|
|
}
|
|
/* @} */
|
|
|
|
// 如果能连接到已有曲线,则分析下一条边
|
|
if (!isSep) continue;
|
|
// 如果不能连接到已有曲线,则自成一条新的曲线
|
|
else {
|
|
CWire w;
|
|
w.MakeWire.Add(edge);
|
|
w.Start = start;
|
|
w.End = end;
|
|
wiresList.push_back(w);
|
|
continue;
|
|
}
|
|
}
|
|
// 检测封闭性,计算包围盒
|
|
for (auto wire : wiresList) {
|
|
if (!wire.isClosed()) {
|
|
printLog(tr("The selected sketch contains several open profile."), 3);
|
|
return false;
|
|
}
|
|
else {
|
|
BRepBndLib::Add(wire.MakeWire.Shape(), wire.Bound);
|
|
}
|
|
}
|
|
/* 按包围盒大小排序 */
|
|
/* @{ */
|
|
for (int i = 0; i < wiresList.size() - 1; ++i) {
|
|
int n = i;
|
|
while (n >= 0 && wiresList.at(n).Bound.IsOut(wiresList.at(n + 1).Bound)) {
|
|
auto temp = wiresList.at(n);
|
|
wiresList[n] = wiresList[n + 1];
|
|
wiresList[n + 1] = temp;
|
|
n--;
|
|
}
|
|
}
|
|
/* @} */
|
|
|
|
// 初始化组合对象。
|
|
BRep_Builder builder;
|
|
TopoDS_Compound compoundSolid;
|
|
builder.MakeCompound(compoundSolid);
|
|
|
|
auto count = wiresList.size();
|
|
for (int i = 0; i < count; ++i) {
|
|
auto wire = wiresList.at(i);
|
|
BRepBuilderAPI_MakeFace face(wire.MakeWire, true);
|
|
if (count > i + 1) {
|
|
CWire cwire = wiresList.at(i + 1);
|
|
TopoDS_Shape innerShape = cwire.MakeWire.Shape();
|
|
if (innerShape.ShapeType() != TopAbs_WIRE) return false;
|
|
TopoDS_Wire innerWire = TopoDS::Wire(innerShape);
|
|
if (innerWire.IsNull()) return false;
|
|
innerWire.Reverse();
|
|
face.Add(innerWire);
|
|
++i;
|
|
}
|
|
face.Build();
|
|
if (!face.IsDone()) return false;
|
|
builder.Add(compoundSolid, BRepPrimAPI_MakePrism(face, dir).Shape());
|
|
}
|
|
|
|
_occShapeAgent->updateShape(compoundSolid);
|
|
}
|
|
else {
|
|
_occShapeAgent->updateShape(BRepPrimAPI_MakePrism(topoShape, dir).Shape());
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
printLog(tr("Failed to make solid!"), 3);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
FITKOCCModelRevolSolid::FITKOCCModelRevolSolid() : OCCShapeAgent(this)
|
|
{
|
|
_shapeAgent = _occShapeAgent;
|
|
}
|
|
bool FITKOCCModelRevolSolid::update()
|
|
{
|
|
auto geoCmdList = FITKGLODATA->getGeometryData<Interface::FITKGeoCommandList>();
|
|
|
|
auto cmd = geoCmdList->getDataByID(m_SourceSurface.CmdId);
|
|
if (cmd == nullptr) return false;
|
|
|
|
Interface::FITKGeoEnum::VTopoShapeType type = cmd->getGeometryCommandType() == Interface::FITKGeoEnum::FITKGeometryComType::FGTSketch2D ? Interface::FITKGeoEnum::VTopoShapeType::VSAssembly : Interface::FITKGeoEnum::VTopoShapeType::VSFace;
|
|
|
|
auto vshape = cmd->getShapeT<FITKOCCTopoShape>(type, m_SourceSurface.VirtualTopoId);
|
|
if (vshape == nullptr) return false;
|
|
auto topoShape = vshape->getTopoShape();
|
|
//m_OriginId;
|
|
gp_Ax1 ax1(
|
|
gp_Pnt(m_RotateAxisPoint1[0], m_RotateAxisPoint1[1], m_RotateAxisPoint1[2]),
|
|
gp_Dir(m_RotateAxisPoint2[0] - m_RotateAxisPoint1[0], m_RotateAxisPoint2[1] - m_RotateAxisPoint1[1], m_RotateAxisPoint2[2] - m_RotateAxisPoint1[2]));
|
|
try {
|
|
// 如果是草绘则返回的是线的组合体,需要合并面
|
|
if (topoShape.ShapeType() == TopAbs_ShapeEnum::TopAbs_COMPOUND)
|
|
{
|
|
TopoDS_Compound compound = TopoDS::Compound(topoShape);
|
|
TopExp_Explorer exp;
|
|
|
|
|
|
QList<CWire> wiresList{};
|
|
|
|
// 按封闭曲线分组
|
|
for (exp.Init(compound, TopAbs_EDGE); exp.More(); exp.Next())
|
|
{
|
|
TopoDS_Edge edge = TopoDS::Edge(exp.Current());
|
|
if (edge.IsNull()) continue;
|
|
|
|
Standard_Real first;
|
|
Standard_Real last;
|
|
Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, first, last);
|
|
gp_Pnt start = curve->Value(first);
|
|
gp_Pnt end = curve->Value(last);
|
|
|
|
/* 自成封闭的曲线 */
|
|
/* @{ */
|
|
if (start.Distance(end) < Precision::Confusion()) {
|
|
CWire w;
|
|
w.MakeWire.Add(edge);
|
|
w.Start = start;
|
|
w.End = end;
|
|
wiresList.push_back(w);
|
|
continue;
|
|
}
|
|
/* @} */
|
|
|
|
/* 是否能拼接到已有曲线 */
|
|
/* @{ */
|
|
bool isSep{ true };
|
|
for (auto& wire : wiresList) {
|
|
// 已经闭合的曲线不参与比较
|
|
if (wire.isClosed()) continue;
|
|
if (wire.Start.Distance(start) < Precision::Confusion())
|
|
{
|
|
wire.MakeWire.Add(edge);
|
|
wire.Start = end;
|
|
isSep = false;
|
|
break;
|
|
}
|
|
else if (wire.Start.Distance(end) < Precision::Confusion())
|
|
{
|
|
wire.MakeWire.Add(edge);
|
|
wire.Start = start;
|
|
isSep = false;
|
|
break;
|
|
}
|
|
else if (wire.End.Distance(start) < Precision::Confusion())
|
|
{
|
|
wire.MakeWire.Add(edge);
|
|
wire.End = end;
|
|
isSep = false;
|
|
break;
|
|
}
|
|
else if (wire.End.Distance(end) < Precision::Confusion())
|
|
{
|
|
wire.MakeWire.Add(edge);
|
|
wire.End = start;
|
|
isSep = false;
|
|
break;
|
|
}
|
|
else {
|
|
printLog(QString("wire.Start: [%1, %2, %3]; wire.End: [%4, %5, %6]").arg(wire.Start.X()).arg(wire.Start.Y()).arg(wire.Start.Z()).arg(wire.End.X()).arg(wire.End.Y()).arg(wire.End.Z()), 2);
|
|
printLog(QString("Start: [%1, %2, %3]; End: [%4, %5, %6]").arg(start.X()).arg(start.Y()).arg(start.Z()).arg(end.X()).arg(end.Y()).arg(end.Z()), 2);
|
|
}
|
|
}
|
|
/* @} */
|
|
|
|
// 如果能连接到已有曲线,则分析下一条边
|
|
if (!isSep) continue;
|
|
// 如果不能连接到已有曲线,则自成一条新的曲线
|
|
else {
|
|
CWire w;
|
|
w.MakeWire.Add(edge);
|
|
w.Start = start;
|
|
w.End = end;
|
|
wiresList.push_back(w);
|
|
continue;
|
|
}
|
|
}
|
|
// 检测封闭性,计算包围盒
|
|
for (auto wire : wiresList) {
|
|
if (!wire.isClosed()) {
|
|
printLog(tr("The selected sketch contains several open profile."), 3);
|
|
return false;
|
|
}
|
|
else {
|
|
BRepBndLib::Add(wire.MakeWire.Shape(), wire.Bound);
|
|
}
|
|
}
|
|
/* 按包围盒大小排序 */
|
|
/* @{ */
|
|
for (int i = 0; i < wiresList.size() - 1; ++i) {
|
|
int n = i;
|
|
while (n >= 0 && wiresList.at(n).Bound.IsOut(wiresList.at(n + 1).Bound)) {
|
|
auto temp = wiresList.at(n);
|
|
wiresList[n] = wiresList[n + 1];
|
|
wiresList[n + 1] = temp;
|
|
n--;
|
|
}
|
|
}
|
|
/* @} */
|
|
|
|
// 初始化组合对象。
|
|
BRep_Builder builder;
|
|
TopoDS_Compound compoundSolid;
|
|
builder.MakeCompound(compoundSolid);
|
|
|
|
auto count = wiresList.size();
|
|
for (int i = 0; i < count; ++i) {
|
|
auto wire = wiresList.at(i);
|
|
BRepBuilderAPI_MakeFace face(wire.MakeWire, true);
|
|
if (count > i + 1) {
|
|
CWire cwire = wiresList.at(i + 1);
|
|
TopoDS_Shape innerShape = cwire.MakeWire.Shape();
|
|
if (innerShape.ShapeType() != TopAbs_WIRE) return false;
|
|
TopoDS_Wire innerWire = TopoDS::Wire(innerShape);
|
|
if (innerWire.IsNull()) return false;
|
|
innerWire.Reverse();
|
|
face.Add(innerWire);
|
|
++i;
|
|
}
|
|
face.Build();
|
|
if (!face.IsDone()) return false;
|
|
builder.Add(compoundSolid, BRepPrimAPI_MakeRevol(face, ax1, m_Angle * M_PI / 180).Shape());
|
|
}
|
|
|
|
_occShapeAgent->updateShape(compoundSolid);
|
|
}
|
|
else {
|
|
_occShapeAgent->updateShape(BRepPrimAPI_MakeRevol(topoShape, ax1, m_Angle * M_PI / 180).Shape());
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
printLog(tr("Failed to make solid!"), 3);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
FITKOCCModelSweepSolid::FITKOCCModelSweepSolid() : OCCShapeAgent(this)
|
|
{
|
|
_shapeAgent = _occShapeAgent;
|
|
}
|
|
bool FITKOCCModelSweepSolid::update()
|
|
{
|
|
auto geoCmdList = FITKGLODATA->getGeometryData<Interface::FITKGeoCommandList>();
|
|
|
|
auto profileCmd = geoCmdList->getDataByID(m_Profile.CmdId);
|
|
auto curveCmd = geoCmdList->getDataByID(m_Curve.CmdId);
|
|
if (profileCmd == nullptr || curveCmd == nullptr) return false;
|
|
|
|
Interface::FITKGeoEnum::VTopoShapeType profileType = profileCmd->getGeometryCommandType() == Interface::FITKGeoEnum::FITKGeometryComType::FGTSketch2D ? Interface::FITKGeoEnum::VTopoShapeType::VSAssembly : Interface::FITKGeoEnum::VTopoShapeType::VSFace;
|
|
auto profileShape = profileCmd->getShapeT<FITKOCCTopoShape>(profileType, m_Profile.VirtualTopoId);
|
|
|
|
Interface::FITKGeoEnum::VTopoShapeType curveType = curveCmd->getGeometryCommandType() == Interface::FITKGeoEnum::FITKGeometryComType::FGTSketch2D ? Interface::FITKGeoEnum::VTopoShapeType::VSAssembly : Interface::FITKGeoEnum::VTopoShapeType::VSEdge;
|
|
auto curveShape = curveCmd->getShapeT<FITKOCCTopoShape>(curveType, m_Curve.VirtualTopoId);
|
|
if (profileShape == nullptr || curveShape == nullptr) return false;
|
|
|
|
auto profileTopoShape = profileShape->getTopoShape();
|
|
auto curveTopoShape = curveShape->getTopoShape();
|
|
|
|
try {
|
|
/* 分析扫略线 */
|
|
/*@{*/
|
|
TopoDS_Wire sweepWire;
|
|
auto type = curveTopoShape.ShapeType();
|
|
if (type == TopAbs_ShapeEnum::TopAbs_WIRE)
|
|
{
|
|
sweepWire = TopoDS::Wire(curveTopoShape);
|
|
}
|
|
else if (type == TopAbs_ShapeEnum::TopAbs_EDGE) {
|
|
sweepWire = BRepBuilderAPI_MakeWire(TopoDS::Edge(curveTopoShape));
|
|
}
|
|
else if (type == TopAbs_ShapeEnum::TopAbs_COMPOUND) {
|
|
TopoDS_Compound compound = TopoDS::Compound(curveTopoShape);
|
|
TopExp_Explorer exp;
|
|
BRepBuilderAPI_MakeWire makeWire;
|
|
for (exp.Init(compound, TopAbs_EDGE); exp.More(); exp.Next())
|
|
{
|
|
TopoDS_Edge edge = TopoDS::Edge(exp.Current());
|
|
if (edge.IsNull()) continue;
|
|
makeWire.Add(edge);
|
|
}
|
|
makeWire.Build();
|
|
if (!makeWire.IsDone()) return false;
|
|
sweepWire = TopoDS::Wire(makeWire.Shape());
|
|
}
|
|
else return false;
|
|
/*@}*/
|
|
|
|
|
|
// 如果是草绘则返回的是线的组合体,需要合并面
|
|
if (profileTopoShape.ShapeType() == TopAbs_ShapeEnum::TopAbs_COMPOUND)
|
|
{
|
|
TopoDS_Compound compound = TopoDS::Compound(profileTopoShape);
|
|
TopExp_Explorer exp;
|
|
|
|
|
|
QList<CWire> wiresList{};
|
|
|
|
// 按封闭曲线分组
|
|
for (exp.Init(compound, TopAbs_EDGE); exp.More(); exp.Next())
|
|
{
|
|
TopoDS_Edge edge = TopoDS::Edge(exp.Current());
|
|
if (edge.IsNull()) continue;
|
|
|
|
Standard_Real first;
|
|
Standard_Real last;
|
|
Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, first, last);
|
|
gp_Pnt start = curve->Value(first);
|
|
gp_Pnt end = curve->Value(last);
|
|
|
|
/* 自成封闭的曲线 */
|
|
/* @{ */
|
|
if (start.Distance(end) < Precision::Confusion()) {
|
|
CWire w;
|
|
w.MakeWire.Add(edge);
|
|
w.Start = start;
|
|
w.End = end;
|
|
wiresList.push_back(w);
|
|
continue;
|
|
}
|
|
/* @} */
|
|
|
|
/* 是否能拼接到已有曲线 */
|
|
/* @{ */
|
|
bool isSep{ true };
|
|
for (auto& wire : wiresList) {
|
|
// 已经闭合的曲线不参与比较
|
|
if (wire.isClosed()) continue;
|
|
if (wire.Start.Distance(start) < Precision::Confusion())
|
|
{
|
|
wire.MakeWire.Add(edge);
|
|
wire.Start = end;
|
|
isSep = false;
|
|
break;
|
|
}
|
|
else if (wire.Start.Distance(end) < Precision::Confusion())
|
|
{
|
|
wire.MakeWire.Add(edge);
|
|
wire.Start = start;
|
|
isSep = false;
|
|
break;
|
|
}
|
|
else if (wire.End.Distance(start) < Precision::Confusion())
|
|
{
|
|
wire.MakeWire.Add(edge);
|
|
wire.End = end;
|
|
isSep = false;
|
|
break;
|
|
}
|
|
else if (wire.End.Distance(end) < Precision::Confusion())
|
|
{
|
|
wire.MakeWire.Add(edge);
|
|
wire.End = start;
|
|
isSep = false;
|
|
break;
|
|
}
|
|
else {
|
|
printLog(QString("wire.Start: [%1, %2, %3]; wire.End: [%4, %5, %6]").arg(wire.Start.X()).arg(wire.Start.Y()).arg(wire.Start.Z()).arg(wire.End.X()).arg(wire.End.Y()).arg(wire.End.Z()), 2);
|
|
printLog(QString("Start: [%1, %2, %3]; End: [%4, %5, %6]").arg(start.X()).arg(start.Y()).arg(start.Z()).arg(end.X()).arg(end.Y()).arg(end.Z()), 2);
|
|
}
|
|
}
|
|
/* @} */
|
|
|
|
// 如果能连接到已有曲线,则分析下一条边
|
|
if (!isSep) continue;
|
|
// 如果不能连接到已有曲线,则自成一条新的曲线
|
|
else {
|
|
CWire w;
|
|
w.MakeWire.Add(edge);
|
|
w.Start = start;
|
|
w.End = end;
|
|
wiresList.push_back(w);
|
|
continue;
|
|
}
|
|
}
|
|
// 检测封闭性,计算包围盒
|
|
for (auto wire : wiresList) {
|
|
if (!wire.isClosed()) {
|
|
printLog(tr("The selected sketch contains several open profile."), 3);
|
|
return false;
|
|
}
|
|
else {
|
|
BRepBndLib::Add(wire.MakeWire.Shape(), wire.Bound);
|
|
}
|
|
}
|
|
/* 按包围盒大小排序 */
|
|
/* @{ */
|
|
for (int i = 0; i < wiresList.size() - 1; ++i) {
|
|
int n = i;
|
|
while (n >= 0 && wiresList.at(n).Bound.IsOut(wiresList.at(n + 1).Bound)) {
|
|
auto temp = wiresList.at(n);
|
|
wiresList[n] = wiresList[n + 1];
|
|
wiresList[n + 1] = temp;
|
|
n--;
|
|
}
|
|
}
|
|
/* @} */
|
|
|
|
// 初始化组合对象。
|
|
BRep_Builder builder;
|
|
TopoDS_Compound compoundSolid;
|
|
builder.MakeCompound(compoundSolid);
|
|
|
|
auto count = wiresList.size();
|
|
for (int i = 0; i < count; ++i) {
|
|
auto wire = wiresList.at(i);
|
|
BRepBuilderAPI_MakeFace face(wire.MakeWire, true);
|
|
if (count > i + 1) {
|
|
CWire cwire = wiresList.at(i + 1);
|
|
TopoDS_Shape innerShape = cwire.MakeWire.Shape();
|
|
if (innerShape.ShapeType() != TopAbs_WIRE) return false;
|
|
TopoDS_Wire innerWire = TopoDS::Wire(innerShape);
|
|
if (innerWire.IsNull()) return false;
|
|
innerWire.Reverse();
|
|
face.Add(innerWire);
|
|
++i;
|
|
}
|
|
face.Build();
|
|
if (!face.IsDone()) return false;
|
|
builder.Add(compoundSolid, BRepOffsetAPI_MakePipe(sweepWire, face).Shape());
|
|
}
|
|
|
|
_occShapeAgent->updateShape(compoundSolid);
|
|
}
|
|
else {
|
|
BRepOffsetAPI_MakePipe pipe(sweepWire, profileTopoShape);
|
|
pipe.Build();
|
|
if (!pipe.IsDone()) return false;
|
|
_occShapeAgent->updateShape(pipe.Shape());
|
|
}
|
|
return true;
|
|
}
|
|
catch (...)
|
|
{
|
|
printLog(tr("Failed to make solid!"), 3);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
FITKOCCModelMultiSectionSolid::FITKOCCModelMultiSectionSolid() : OCCShapeAgent(this)
|
|
{
|
|
_shapeAgent = _occShapeAgent;
|
|
}
|
|
|
|
bool FITKOCCModelMultiSectionSolid::update()
|
|
{
|
|
if (m_Sections.size() < 2) return false;
|
|
|
|
auto geoCmdList = FITKGLODATA->getGeometryData<Interface::FITKGeoCommandList>();
|
|
|
|
BRepOffsetAPI_ThruSections thruSection(true);
|
|
|
|
for (auto section : m_Sections) {
|
|
auto cmd = geoCmdList->getDataByID(section.CmdId);
|
|
if (cmd == nullptr) return false;
|
|
Interface::FITKGeoEnum::VTopoShapeType type = cmd->getGeometryCommandType() == Interface::FITKGeoEnum::FITKGeometryComType::FGTSketch2D ? Interface::FITKGeoEnum::VTopoShapeType::VSAssembly : Interface::FITKGeoEnum::VTopoShapeType::VSEdge;
|
|
auto vshape = cmd->getShapeT<FITKOCCTopoShape>(type, section.VirtualTopoId);
|
|
if (vshape == nullptr) return false;
|
|
auto topoShape = vshape->getTopoShape();
|
|
|
|
if (topoShape.ShapeType() == TopAbs_ShapeEnum::TopAbs_EDGE) {
|
|
BRepLib_MakeWire wire(TopoDS::Edge(topoShape));
|
|
thruSection.AddWire(wire.Wire());
|
|
}
|
|
else if (topoShape.ShapeType() == TopAbs_ShapeEnum::TopAbs_WIRE) {
|
|
thruSection.AddWire(TopoDS::Wire(topoShape));
|
|
}
|
|
else if (topoShape.ShapeType() == TopAbs_ShapeEnum::TopAbs_COMPOUND) {
|
|
TopExp_Explorer exp;
|
|
BRepLib_MakeWire wire;
|
|
// 按封闭曲线分组
|
|
for (exp.Init(topoShape, TopAbs_EDGE); exp.More(); exp.Next())
|
|
{
|
|
TopoDS_Edge edge = TopoDS::Edge(exp.Current());
|
|
if (edge.IsNull()) continue;
|
|
wire.Add(edge);
|
|
}
|
|
try
|
|
{
|
|
wire.Build();
|
|
if (!wire.IsDone()) return false;
|
|
thruSection.AddWire(wire.Wire());
|
|
}
|
|
catch (...)
|
|
{
|
|
printLog(tr("Failed to make wire!"), 3);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
try {
|
|
thruSection.Build();
|
|
if (!thruSection.IsDone()) return false;
|
|
_occShapeAgent->updateShape(thruSection.Shape());
|
|
}
|
|
catch (...)
|
|
{
|
|
printLog(tr("Failed to make solid!"), 3);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
}
|