5.2 KiB
Primitive Placement Progress
Later continuation: active-container membership/display and Cylinder skew are implemented with focused evidence. Use that progress note for the current remaining list; do not repeat placement, container or skew work based on the historical next-gap list below.
Updated 2026-09-17. Part:desktop:Part_Primitives remains incomplete.
This increment implements manual position and axis-angle controls. It does
not replay earlier primitive-type or IFC acceptance suites.
Implementation
setPrimitiveaccepts optionalprimitivePlacementwith position, axis and angle in degrees. Native FreeCADPlacementandRotationperform the transformation. Creation or editing changes dimensions and placement in one document transaction. Omitted placement preserves existing placement for older callers. New objects still use the existing unique-name behavior.- Both facade and native routes reject malformed/nonfinite vectors, angles and overflowing axis norms. A non-unit axis is normalized; a zero axis is accepted only for an identity rotation. Native snapshots return canonical placement, and the facade compares rotation equivalence rather than raw axis-angle spelling.
- The existing task now exposes XYZ position, XYZ rotation axis, degree angle and a reset-placement icon. Read, cancel, undo/redo, selected-object changes and FCStd opening restore the native values. Changing document resets the placement draft. Solid mesh vertices, line vertices and point markers are the transformed native geometry; no separate visual-only transform is used.
- A recompute can override placement through a native expression or attachment. The route now checks the resulting placement before committing. A mismatch aborts the whole transaction, including dimensional changes. The executable expression-conflict case verifies unchanged geometry, parameters, placement, binding and undo/redo counts through facade and direct-native routes.
Desktop source: DlgPrimitives.cpp, Location::refresh,
Location::onPlacementChanged, DlgPrimitives::acceptChanges, and the primitive
creation/change methods. Existing native properties and serialization are reused.
Evidence
Active increment: tools/part-primitive-placement-business-cases.mjs, exported
as runPrimitiveTaskCases. The earlier type-specific helpers remain preserved
and deferred. The focused helper loads one native runtime and one browser.
python3 tools/run_business_acceptance.py --module Part --ids Part:desktop:Part_Primitives --reuse
Final report:
docs/current/business-evidence/13fb362e5bcf598a7f1f90a6-20260917T101840425546.json.
Eight new scenario groups completed without assertion errors, 18.523 seconds.
The whole-command result is intentionally not_implemented; the runner reports
acceptance_incomplete, passed=0. These eight groups are not eight requirements.
Coverage includes independently transformed Box/Line/Vertex coordinates, non-unit and arbitrary axes, signed angles, identity rotation, combined dimension/placement atomic undo, preservation when placement is omitted, malformed input rejection, document isolation, expression-conflict rollback, FCStd save/reopen/edit, browser invalid-axis/cancel/reset controls, history, OPFS reload and further editing, viewport orbit and nonblank canvas checks at 1440x900 and 390x844. Desktop and mobile screenshots were visually inspected.
Detailed results and images:
docs/current/part-primitive-placement-business/2026-09-17T10-18-22-215Z/.
The initial seven-group run is preserved in report 20260917T101131013838.
The later 20260917T101653809041 run exposed an assertion expecting the literal
path Placement.Base.x; FreeCAD reports .Placement.Base.x. A focused native
read confirmed the canonical path and x=7. The corrected case compares the
complete native binding before and after rollback and checks the constrained
coordinate, without removing the binding-preservation requirement.
Native DocumentProbe build, TypeScript checking, Vite production build and scoped native whitespace checks completed. Shared build contention was resolved by letting the existing writer release its lock. Acceptance ran with background shared-file writes paused. The same unattended service is resumed afterward; no duplicate scheduler was started.
Existing application:
http://127.0.0.1:5180/workbench.html?module=Part&command=Part_Primitives.
Next Gaps
All sixteen primitive types have already been added; see
PART_HELIX_SPIRAL_PROGRESS.md and its earlier references. Do not reimplement
them, refresh old evidence, or replay this placement helper unchanged.
Continue with an unimplemented interaction and give it new focused cases:
- Active App::Part container controls and creation membership. Desktop anchor:
DlgPrimitives.cpp::getAutoGroupCommandStrandtryCreatePrimitive. - Cylinder skew controls and circle-from-three-points interaction.
- Desktop location picking, expression editing/binding UI, and live task preview/accept/reject lifecycle parity. Manual placement Apply and rollback protection do not certify those additional workflows.
The complete original 1507 plus supplemental IFC requirement set is preserved. No whole-command acceptance or aggregate coverage increase is claimed here.