Merge pull request #27127 from alfrix/fix_tapered

PD: hole fix tapered threads not cutting properly
This commit is contained in:
Kacper Donat
2026-02-23 17:42:24 +01:00
committed by GitHub
2 changed files with 58 additions and 22 deletions
+37 -11
View File
@@ -29,6 +29,8 @@
#include <App/FeaturePythonPyImp.h>
#include <Mod/Part/App/modelRefine.h>
#include <Mod/Part/App/TopoShapeOpCode.h>
#include <GProp_GProps.hxx>
#include <BRepGProp.hxx>
#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;
}
+21 -11
View File
@@ -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<TopoShape> 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<TopoShape>& holes,
const TopoShape& profileshape,