From 234d69e58b69db5922029b5f97bba8a99cda6e2e Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Sun, 23 Nov 2025 23:04:14 +0100 Subject: [PATCH 1/3] PartDesign: Simplify FeatureBoolean This commit removes a ton of dead code from FeatureBoolean. It might been ported here from the Link branch but it is not used and it is confusing. The reason for having that code here is also not really obvious so there is no reason to keep it. --- src/Mod/PartDesign/App/FeatureBoolean.cpp | 52 ++--------------------- src/Mod/PartDesign/App/FeatureBoolean.h | 2 - src/Mod/PartDesign/Gui/Command.cpp | 1 - 3 files changed, 3 insertions(+), 52 deletions(-) diff --git a/src/Mod/PartDesign/App/FeatureBoolean.cpp b/src/Mod/PartDesign/App/FeatureBoolean.cpp index 85708c5d12..a6dec043a0 100644 --- a/src/Mod/PartDesign/App/FeatureBoolean.cpp +++ b/src/Mod/PartDesign/App/FeatureBoolean.cpp @@ -40,10 +40,9 @@ using namespace PartDesign; namespace PartDesign { - extern bool getPDRefineModelParameter(); -PROPERTY_SOURCE_WITH_EXTENSIONS(PartDesign::Boolean, PartDesign::Feature) +PROPERTY_SOURCE_WITH_EXTENSIONS(PartDesign::Boolean, PartDesign::FeatureRefine) const char* Boolean::TypeEnums[] = {"Fuse", "Cut", "Common", nullptr}; @@ -52,15 +51,6 @@ Boolean::Boolean() ADD_PROPERTY(Type, ((long)0)); Type.setEnums(TypeEnums); - ADD_PROPERTY_TYPE( - UsePlacement, - (0), - "Part Design", - (App::PropertyType)(App::Prop_None), - "Apply the placement of the second ( tool ) object" - ); - this->UsePlacement.setValue(false); - App::GeoFeatureGroupExtension::initExtension(this); } @@ -115,15 +105,6 @@ App::DocumentObjectExecReturn* Boolean::execute() ); } - // get the body this boolean feature belongs to - Part::BodyBase* baseBody = Part::BodyBase::findBodyOf(this); - - if (!baseBody) { - return new App::DocumentObjectExecReturn( - QT_TRANSLATE_NOOP("Exception", "Cannot do boolean on feature which is not in a body") - ); - } - std::vector shapes; shapes.push_back(baseTopShape); for (auto it = tools.begin(); it < tools.end(); ++it) { @@ -137,36 +118,9 @@ App::DocumentObjectExecReturn* Boolean::execute() } TopoShape result(baseTopShape); - Base::Placement bodyPlacement = baseBody->globalPlacement().inverse(); - for (auto tool : tools) { - if (!tool->isDerivedFrom()) { - return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP( - "Exception", - "Cannot do boolean with anything but Part::Feature and its derivatives" - )); - } - - Part::TopoShape toolShape = static_cast(tool)->Shape.getShape(); - if (UsePlacement.getValue()) { - toolShape.setPlacement(bodyPlacement * toolShape.getPlacement()); - } - TopoDS_Shape shape = toolShape.getShape(); - TopoDS_Shape boolOp; - - // Must not pass null shapes to the boolean operations - if (result.isNull()) { - return new App::DocumentObjectExecReturn( - QT_TRANSLATE_NOOP("Exception", "Base shape is null") - ); - } - - if (shape.IsNull()) { - return new App::DocumentObjectExecReturn( - QT_TRANSLATE_NOOP("Exception", "Tool shape is null") - ); - } - + if (!tools.empty()) { const char* op = nullptr; + if (type == "Fuse") { op = Part::OpCodes::Fuse; } diff --git a/src/Mod/PartDesign/App/FeatureBoolean.h b/src/Mod/PartDesign/App/FeatureBoolean.h index 2da2fdf934..495fe88ab4 100644 --- a/src/Mod/PartDesign/App/FeatureBoolean.h +++ b/src/Mod/PartDesign/App/FeatureBoolean.h @@ -46,8 +46,6 @@ public: /// The type of the boolean operation App::PropertyEnumeration Type; - App::PropertyBool UsePlacement; - /** @name methods override feature */ //@{ /// Recalculate the feature diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index 2fa11384df..0e287db538 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -2598,7 +2598,6 @@ void CmdPartDesignBoolean::activated(int iMsg) std::string FeatName = getUniqueObjectName("Boolean", pcActiveBody); FCMD_OBJ_CMD(pcActiveBody, "newObject('PartDesign::Boolean','" << FeatName << "')"); auto Feat = pcActiveBody->getDocument()->getObject(FeatName.c_str()); - static_cast(Feat)->UsePlacement.setValue(true); // If we don't add an object to the boolean group then don't update the body // as otherwise this will fail and it will be marked as invalid From 791d6b602c22685e9b8c4fb685a1337f41b74aa3 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Sun, 23 Nov 2025 23:05:46 +0100 Subject: [PATCH 2/3] Part: Add bakeInTransform method for TopoShape This method can be used to bake in transform directly into geometry. Normally the setTransform or setPlacement methods only store additional positional data within the shape without changing the actual geometry. So if we have some geometry placed at 0,0,0 and we want to have few copies of that shape the goemetry stays intact but additional transform is stored. This method can be used to alter the gometry and reset the transform to identity. It helps with model stability, as not every method correctly handles that additional transform metadata. --- src/Mod/Part/App/TopoShape.cpp | 24 ++++++++++++++++++++++++ src/Mod/Part/App/TopoShape.h | 1 + 2 files changed, 25 insertions(+) diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index b706dae74e..a3852749d7 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -3267,6 +3267,30 @@ void TopoShape::transformGeometry(const Base::Matrix4D& rclMat) } } +void TopoShape::bakeInTransform() +{ + if (getShape().IsNull()) { + return; + } + + if (shapeType() != TopAbs_COMPOUND) { + transformGeometry(getTransform()); + setTransform(Base::Matrix4D {}); + return; + } + + TopoShape result; + std::vector shapes; + + for (auto& subshape : getSubTopoShapes()) { + subshape.bakeInTransform(); + shapes.push_back(subshape); + } + + result.makeCompound(shapes); + *this = result; +} + TopoDS_Shape TopoShape::transformGShape(const Base::Matrix4D& rclTrf, bool copy) const { if (this->_Shape.IsNull()) { diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index 3f716f4640..f5733222f2 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -668,6 +668,7 @@ public: /** @name Manipulation*/ //@{ void transformGeometry(const Base::Matrix4D& rclMat) override; + void bakeInTransform(); TopoDS_Shape transformGShape(const Base::Matrix4D&, bool copy = false) const; bool transformShape(const Base::Matrix4D&, bool copy, bool checkScale = false); TopoDS_Shape mirror(const gp_Ax2&) const; From 8f8ba2dad0ca7691ccbe7934c41bb59fa8833608 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Sun, 23 Nov 2025 23:09:20 +0100 Subject: [PATCH 3/3] PartDesign: Bake in geometry transform after boolean This bakes in transform into geometry after boolean to ensure that regardless of parameters the result of boolean operation is the same. --- src/Mod/PartDesign/App/FeatureBoolean.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Mod/PartDesign/App/FeatureBoolean.cpp b/src/Mod/PartDesign/App/FeatureBoolean.cpp index a6dec043a0..12ea7e413b 100644 --- a/src/Mod/PartDesign/App/FeatureBoolean.cpp +++ b/src/Mod/PartDesign/App/FeatureBoolean.cpp @@ -153,6 +153,8 @@ App::DocumentObjectExecReturn* Boolean::execute() } } + result.bakeInTransform(); + result = refineShapeIfActive(result); if (!isSingleSolidRuleSatisfied(result.getShape())) {