PD: SubtractivePipe Fails
Fixes issue 18003
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
# include <TopTools_HSequenceOfShape.hxx>
|
||||
|
||||
|
||||
#include <App/Document.h>
|
||||
#include <App/DocumentObject.h>
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/Reader.h>
|
||||
@@ -151,7 +152,6 @@ App::DocumentObjectExecReturn *Pipe::execute()
|
||||
// As the shell begins always at the spine and not the profile, the sketchshape
|
||||
// cannot be used directly as front face. We would need a method to translate
|
||||
// the front shape to match the shell starting position somehow...
|
||||
std::vector<TopoDS_Wire> wires;
|
||||
TopoDS_Shape profilePoint;
|
||||
|
||||
// if the Base property has a valid shape, fuse the pipe into it
|
||||
@@ -162,6 +162,8 @@ App::DocumentObjectExecReturn *Pipe::execute()
|
||||
base = TopoShape();
|
||||
}
|
||||
|
||||
auto hasher = getDocument()->getStringHasher();
|
||||
|
||||
try {
|
||||
// setup the location
|
||||
this->positionByPrevious();
|
||||
@@ -287,7 +289,7 @@ App::DocumentObjectExecReturn *Pipe::execute()
|
||||
"Exception", "Path must not be a null shape"));
|
||||
|
||||
// build all shells
|
||||
std::vector<TopoDS_Shape> shells;
|
||||
std::vector<TopoShape> shells;
|
||||
|
||||
TopoDS_Shape copyProfilePoint(profilePoint);
|
||||
if (!profilePoint.IsNull())
|
||||
@@ -320,7 +322,7 @@ App::DocumentObjectExecReturn *Pipe::execute()
|
||||
if (!mkPS.IsReady())
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pipe could not be built"));
|
||||
|
||||
shells.push_back(mkPS.Shape());
|
||||
shells.emplace_back(mkPS.Shape());
|
||||
|
||||
if (!mkPS.Shape().Closed()) {
|
||||
// shell is not closed - use simulate to get the end wires
|
||||
@@ -336,8 +338,7 @@ App::DocumentObjectExecReturn *Pipe::execute()
|
||||
}
|
||||
}
|
||||
|
||||
BRepBuilderAPI_MakeSolid mkSolid;
|
||||
|
||||
TopoShape result(0, hasher);
|
||||
if (!frontwires.empty() || !backwires.empty()) {
|
||||
BRepBuilderAPI_Sewing sewer;
|
||||
sewer.SetTolerance(Precision::Confusion());
|
||||
@@ -346,94 +347,103 @@ App::DocumentObjectExecReturn *Pipe::execute()
|
||||
if (!frontwires.empty()) {
|
||||
TopoDS_Shape front = Part::FaceMakerCheese::makeFace(frontwires);
|
||||
sewer.Add(front);
|
||||
shells.emplace_back(front);
|
||||
}
|
||||
if (!backwires.empty()) {
|
||||
TopoDS_Shape back = Part::FaceMakerCheese::makeFace(backwires);
|
||||
sewer.Add(back);
|
||||
shells.emplace_back(back);
|
||||
}
|
||||
for (TopoDS_Shape& s : shells)
|
||||
sewer.Add(s);
|
||||
for (TopoShape& s : shells)
|
||||
sewer.Add(s.getShape());
|
||||
|
||||
sewer.Perform();
|
||||
mkSolid.Add(TopoDS::Shell(sewer.SewedShape())); } else {
|
||||
result = result.makeShapeWithElementMap(sewer.SewedShape(), Part::MapperSewing(sewer), shells, Part::OpCodes::Sewing);
|
||||
} else {
|
||||
// shells are already closed - add them directly
|
||||
for (TopoDS_Shape& s : shells) {
|
||||
mkSolid.Add(TopoDS::Shell(s));
|
||||
BRepBuilderAPI_MakeSolid mkSolid;
|
||||
for (TopoShape& s : shells) {
|
||||
mkSolid.Add(TopoDS::Shell(s.getShape()));
|
||||
}
|
||||
|
||||
if (!mkSolid.IsDone())
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result is not a solid"));
|
||||
result.setShape(mkSolid.Shape());
|
||||
}
|
||||
|
||||
if (!mkSolid.IsDone())
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result is not a solid"));
|
||||
if(!result.countSubShapes(TopAbs_SHELL))
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: Failed to create shell"));
|
||||
|
||||
TopoDS_Shape result = mkSolid.Shape();
|
||||
BRepClass3d_SolidClassifier SC(result);
|
||||
SC.PerformInfinitePoint(Precision::Confusion());
|
||||
if (SC.State() == TopAbs_IN) {
|
||||
result.Reverse();
|
||||
auto shapes = result.getSubTopoShapes(TopAbs_SHELL);
|
||||
for (auto &s : shapes) {
|
||||
// build the solid
|
||||
s = s.makeElementSolid();
|
||||
BRepClass3d_SolidClassifier SC(s.getShape());
|
||||
SC.PerformInfinitePoint(Precision::Confusion());
|
||||
if ( SC.State() == TopAbs_IN)
|
||||
s.setShape(s.getShape().Reversed(),false);
|
||||
}
|
||||
|
||||
//result.Move(invObjLoc);
|
||||
AddSubShape.setValue(result); // Converts result to a TopoShape, but no tag.
|
||||
AddSubShape.setValue(result.makeElementCompound(shapes, nullptr, Part::TopoShape::SingleShapeCompoundCreationPolicy::returnShape));
|
||||
|
||||
if (base.isNull()) {
|
||||
if (shapes.size() > 1)
|
||||
result.makeElementFuse(shapes);
|
||||
else
|
||||
result = shapes.front();
|
||||
|
||||
if(base.isNull()) {
|
||||
if (getAddSubType() == FeatureAddSub::Subtractive)
|
||||
return new App::DocumentObjectExecReturn(
|
||||
QT_TRANSLATE_NOOP("Exception", "Pipe: There is nothing to subtract from"));
|
||||
|
||||
if (!isSingleSolidRuleSatisfied(result.getShape())) {
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: enable 'Allow Compound' in the active body."));
|
||||
}
|
||||
|
||||
// store shape before refinement
|
||||
this->rawShape = result;
|
||||
auto ts_result = refineShapeIfActive(result);
|
||||
Shape.setValue(getSolid(ts_result));
|
||||
|
||||
result = refineShapeIfActive(result);
|
||||
Shape.setValue(getSolid(result));
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
if (getAddSubType() == FeatureAddSub::Additive) {
|
||||
|
||||
FCBRepAlgoAPI_Fuse mkFuse(base.getShape(), result);
|
||||
if (!mkFuse.IsDone())
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Adding the pipe failed"));
|
||||
// we have to get the solids (fuse sometimes creates compounds)
|
||||
TopoShape boolOp = this->getSolid(mkFuse.Shape());
|
||||
// lets check if the result is a solid
|
||||
if (boolOp.isNull())
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
|
||||
|
||||
if (!isSingleSolidRuleSatisfied(boolOp.getShape())) {
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
|
||||
"Result has multiple solids: enable 'Allow Compound' in the active body."));
|
||||
}
|
||||
|
||||
// store shape before refinement
|
||||
this->rawShape = boolOp;
|
||||
boolOp = refineShapeIfActive(boolOp);
|
||||
Shape.setValue(getSolid(boolOp));
|
||||
TopoShape boolOp(0, getDocument()->getStringHasher());
|
||||
const char *maker;
|
||||
switch (getAddSubType()) {
|
||||
case Additive:
|
||||
maker = Part::OpCodes::Fuse;
|
||||
break;
|
||||
case Subtractive:
|
||||
maker = Part::OpCodes::Cut;
|
||||
break;
|
||||
default:
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Unknown operation type"));
|
||||
}
|
||||
else if (getAddSubType() == FeatureAddSub::Subtractive) {
|
||||
|
||||
FCBRepAlgoAPI_Cut mkCut(base.getShape(), result);
|
||||
if (!mkCut.IsDone())
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Subtracting the pipe failed"));
|
||||
// we have to get the solids (fuse sometimes creates compounds)
|
||||
TopoShape boolOp = this->getSolid(mkCut.Shape());
|
||||
// lets check if the result is a solid
|
||||
if (boolOp.isNull())
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
|
||||
|
||||
if (!isSingleSolidRuleSatisfied(boolOp.getShape())) {
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
|
||||
"Result has multiple solids: enable 'Allow Compound' in the active body."));
|
||||
}
|
||||
|
||||
// store shape before refinement
|
||||
this->rawShape = boolOp;
|
||||
boolOp = refineShapeIfActive(boolOp);
|
||||
Shape.setValue(getSolid(boolOp));
|
||||
try {
|
||||
boolOp.makeElementBoolean(maker, {base,result});
|
||||
}
|
||||
catch(Standard_Failure&) {
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Failed to perform boolean operation"));
|
||||
}
|
||||
|
||||
TopoShape solid = getSolid(boolOp);
|
||||
// lets check if the result is a solid
|
||||
if (solid.isNull())
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
|
||||
|
||||
// store shape before refinement
|
||||
this->rawShape = boolOp;
|
||||
boolOp = refineShapeIfActive(boolOp);
|
||||
if (!isSingleSolidRuleSatisfied(boolOp.getShape())) {
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
|
||||
"Result has multiple solids: enable 'Allow Compound' in the active body."));
|
||||
}
|
||||
boolOp = getSolid(boolOp);
|
||||
Shape.setValue(boolOp);
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
catch (Standard_Failure& e) {
|
||||
|
||||
return new App::DocumentObjectExecReturn(e.GetMessageString());
|
||||
}
|
||||
catch (...) {
|
||||
@@ -636,4 +646,3 @@ void Pipe::handleChangedPropertyName(Base::XMLReader& reader,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user