From ddefb236521cfecf334ec883858ed203ddbb8a68 Mon Sep 17 00:00:00 2001 From: forbes Date: Fri, 30 Jan 2026 20:46:32 -0600 Subject: [PATCH] Fix Assembly solver ignoring PartDesign datum plane references MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a PartDesign::Plane (including ZTools datums like ZPlane_Mid, ZPlane_Offset) is used as a reference in an Assembly joint, findPlacement() returns an all-zero placement, making the joint constraint degenerate and ineffective. Root cause: getElementName() strips the terminal '.Plane' suffix because it matches the hardcoded set for App::LocalCoordinateSystem datum elements ({X, Y, Z, Point, Line, Plane}). This is correct behavior — the issue is that findPlacement()'s 'whole part' branch only handled App::Line objects and returned App.Placement() (zeros) for everything else, including PartDesign::Plane datums. The fix extends the 'whole part' branch in findPlacement() to compute a proper placement for PartDesign::Plane objects by extracting the plane's center-of-gravity and surface rotation from its Shape, then converting to object-local coordinates. This matches the existing convention used for Face elements elsewhere in the function. Also adds handling for PartDesign::Point datums, which hit the same empty-element code path. Existing App::Plane origin references (XY_Plane, etc.) are unaffected since isDerivedFrom('PartDesign::Plane') does not match App::Plane. --- src/Mod/Assembly/UtilsAssembly.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Mod/Assembly/UtilsAssembly.py b/src/Mod/Assembly/UtilsAssembly.py index ca26472864..68eddfffbc 100644 --- a/src/Mod/Assembly/UtilsAssembly.py +++ b/src/Mod/Assembly/UtilsAssembly.py @@ -1004,6 +1004,22 @@ def findPlacement(ref, ignoreVertex=False): return App.Placement(App.Vector(), App.Rotation(0.5, 0.5, 0.5, 0.5)) if obj.Role == "Z_Axis": return App.Placement(App.Vector(), App.Rotation(-0.5, 0.5, -0.5, 0.5)) + + # PartDesign datum planes (including ZTools datums like ZPlane_Mid, ZPlane_Offset) + if obj.isDerivedFrom("PartDesign::Plane"): + if hasattr(obj, "Shape") and obj.Shape.Faces: + face = obj.Shape.Faces[0] + surface = face.Surface + plc = App.Placement() + plc.Base = face.CenterOfGravity + if hasattr(surface, "Rotation") and surface.Rotation is not None: + plc.Rotation = App.Rotation(surface.Rotation) + return obj.Placement.inverse() * plc + + # PartDesign datum points + if obj.isDerivedFrom("PartDesign::Point"): + return obj.Placement + return App.Placement() plc = App.Placement()