diff --git a/src/Mod/PartDesign/App/FeatureAddSub.cpp b/src/Mod/PartDesign/App/FeatureAddSub.cpp index 87befbd39c..6d262f2c17 100644 --- a/src/Mod/PartDesign/App/FeatureAddSub.cpp +++ b/src/Mod/PartDesign/App/FeatureAddSub.cpp @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include "FeatureAddSub.h" #include "FeaturePy.h" @@ -77,7 +79,6 @@ void FeatureAddSub::getAddSubShape(Part::TopoShape& addShape, Part::TopoShape& s subShape = AddSubShape.getShape(); } } - void FeatureAddSub::updatePreviewShape() { const auto notifyWarning = [](const QString& message) { @@ -90,10 +91,43 @@ void FeatureAddSub::updatePreviewShape() // for subtractive shapes we want to also showcase removed volume, not only the tool if (addSubType == Subtractive) { TopoShape base = getBaseTopoShape(true).moved(getLocation().Inverted()); + const TopoShape& tool = AddSubShape.getShape(); - if (const TopoShape& addSubShape = AddSubShape.getShape(); !addSubShape.isEmpty()) { + if (!tool.isEmpty()) { try { - base.makeElementBoolean(Part::OpCodes::Common, {base, addSubShape}); + // Compute removed volume preview (for display) + TopoShape common; + common.makeElementBoolean( + Part::OpCodes::Common, + {base, tool}, + "Preview", + Precision::Confusion() + ); + + // does CUT change volume? + GProp_GProps propsBefore, propsAfter; + BRepGProp::VolumeProperties(base.getShape(), propsBefore); + + TopoShape cut; + cut.makeElementBoolean( + Part::OpCodes::Cut, + {base, tool}, + "PreviewCheck", + Precision::Confusion() + ); + + BRepGProp::VolumeProperties(cut.getShape(), propsAfter); + + const double removed = propsBefore.Mass() - propsAfter.Mass(); + + if (removed <= Precision::Confusion()) { + notifyWarning( + tr("Resulting shape is empty. That may indicate that no material will be " + "removed or a problem with the model.") + ); + } + PreviewShape.setValue(common); + return; } catch (Standard_Failure& e) { notifyWarning(QString::fromUtf8(e.GetMessageString())); @@ -101,14 +135,6 @@ void FeatureAddSub::updatePreviewShape() catch (Base::Exception& e) { notifyWarning(QString::fromStdString(e.getMessage())); } - - if (base.isEmpty()) { - notifyWarning( - tr("Resulting shape is empty. That may indicate that no material will be " - "removed or a problem with the model.") - ); - } - PreviewShape.setValue(base); return; } diff --git a/src/Mod/PartDesign/App/FeatureHole.cpp b/src/Mod/PartDesign/App/FeatureHole.cpp index e5aab172d2..3f456d6844 100644 --- a/src/Mod/PartDesign/App/FeatureHole.cpp +++ b/src/Mod/PartDesign/App/FeatureHole.cpp @@ -1962,21 +1962,20 @@ App::DocumentObjectExecReturn* Hole::execute() ); } - // Make thread if (Threaded.getValue() && ModelThread.getValue()) { TopoDS_Shape protoThread = makeThread(xDir, zDir, length); - // fuse the thread to the hole - FCBRepAlgoAPI_Fuse mkFuse(protoHole, protoThread); - if (!mkFuse.IsDone()) { - return new App::DocumentObjectExecReturn( - QT_TRANSLATE_NOOP("Exception", "Error: Adding the thread failed") - ); - } + TopoDS_Compound holeWithThread; + holeWithThread.Nullify(); + + BRep_Builder builder; + builder.MakeCompound(holeWithThread); + builder.Add(holeWithThread, protoHole); + builder.Add(holeWithThread, protoThread); // we reuse the name protoHole (only now it is threaded) - protoHole = mkFuse.Shape(); + protoHole = holeWithThread; } std::vector holes; auto compound = findHoles(holes, profileshape, protoHole); @@ -2012,7 +2011,12 @@ App::DocumentObjectExecReturn* Hole::execute() result = compound; } else { - result.makeElementBoolean(maker, {base, compound}); + result.makeElementBoolean( + maker, + {base, compound}, + getNameInDocument(), + Precision::Confusion() + ); } result = getSolid(result); retry = false; @@ -2034,7 +2038,12 @@ App::DocumentObjectExecReturn* Hole::execute() for (auto& hole : holes) { ++i; try { - result.makeElementBoolean(maker, {base, hole}); + result.makeElementBoolean( + maker, + {base, hole}, + getNameInDocument(), + Precision::Confusion() + ); } catch (Standard_Failure&) { std::string msg( @@ -2171,6 +2180,7 @@ Base::Vector3d Hole::guessNormalDirection(const TopoShape& profileshape) const return getProfileNormal(); } + TopoShape Hole::findHoles( std::vector& holes, const TopoShape& profileshape,