Document the ZTools Datum Creator: SelectionItem geometry classification, 16 creation modes (7 plane, 4 axis, 5 point), auto-detection scoring algorithm, task panel UI layout, parameter sections, dispatch to datums/core.py, and core implementation details.
7.8 KiB
Datum Creator System
The ZTools Datum Creator (ZTools_DatumCreator) creates parametric datum planes, axes, and points. It auto-detects the datum type from selected geometry and provides a unified task panel with 16 creation modes.
Source files:
mods/ztools/ztools/ztools/commands/datum_commands.py-- UI, selection handling, mode detectionmods/ztools/ztools/ztools/datums/core.py-- geometry computation and FreeCAD object creation
Geometry Classification
The SelectionItem class wraps a selected geometry element and classifies it into one of seven types:
| Type | Detection | Icon |
|---|---|---|
| face | Planar Part.Face or object with "Plane" in TypeId |
▢ |
| plane | Datum plane objects or planar faces | ▣ |
| cylinder | Part.Face with Surface.Cylinder |
◎ |
| edge | Part.Edge with Part.Line curve |
― |
| circle | Part.Edge with Part.Circle or Part.ArcOfCircle |
○ |
| vertex | Part.Vertex |
• |
| unknown | Unclassified geometry | ? |
Classification flow:
- Extract shape from object using the sub-element name (Face#, Edge#, Vertex#)
- Check shape type (Face, Edge, Vertex)
- For faces: check
surface.isPlanar()orisinstance(surface, Part.Cylinder) - For edges: check curve type (Line, Circle, ArcOfCircle)
- Fall back to
unknown
Creation Modes
Planes (7 modes)
| Mode | Required Selection | Parameters | Description |
|---|---|---|---|
offset_face |
1 face | distance (mm) | Plane parallel to face at offset |
offset_plane |
1 plane | distance (mm) | Plane parallel to datum plane at offset |
midplane |
2 faces | -- | Plane halfway between two parallel faces |
3_points |
3 vertices | -- | Plane through three non-collinear points |
normal_edge |
1 edge | position (0--1) | Plane perpendicular to edge at parameter |
angled |
1 face + 1 edge | angle (deg) | Plane at angle to face, rotating about edge |
tangent_cyl |
1 cylinder | angle (deg) | Plane tangent to cylinder at angular position |
Axes (4 modes)
| Mode | Required Selection | Parameters | Description |
|---|---|---|---|
axis_2pt |
2 vertices | -- | Axis through two points |
axis_edge |
1 edge | -- | Axis along linear edge |
axis_cyl |
1 cylinder | -- | Axis along cylinder centerline |
axis_intersect |
2 planes | -- | Axis at intersection of two planes |
Points (5 modes)
| Mode | Required Selection | Parameters | Description |
|---|---|---|---|
point_vertex |
1 vertex | -- | Point at vertex location |
point_xyz |
(none) | x, y, z (mm) | Point at explicit coordinates |
point_edge |
1 edge | position (0--1) | Point at parameter location on edge |
point_face |
1 face | -- | Point at center of mass of face |
point_circle |
1 circle | -- | Point at center of circular edge |
Auto-Detection Algorithm
The _match_score() method scores how well the current selection matches each mode's required types.
Scoring:
- If the selection has fewer items than required, score is 0 (no match).
- For each required type, find a matching selected type using fuzzy matching:
facerequirement matchesfaceorcylinderedgerequirement matchesedgeorcircle- All other types require exact match
- Score calculation:
- Exact cardinality (selection count == required count): score =
100 + matched_count - Over-selected (more items than required): score =
matched_count - No match: score =
0
- Exact cardinality (selection count == required count): score =
The mode with the highest score wins. On each selection change, update_mode_from_selection() re-evaluates all 16 modes and activates the best match.
The detected mode is displayed with a category color:
- Planes: Mauve (#cba6f7)
- Axes: Teal (#94e2d5)
- Points: Yellow (#f9e2af)
Task Panel UI
+-------------------------------------+
| ZTools Datum Creator |
+-------------------------------------+
| Selection |
| [icon] Element Name [Remove] |
| [Add Selected] [Remove] [Clear] |
+-------------------------------------+
| Datum Type |
| DETECTED MODE (colored) |
| Override: [dropdown] |
+-------------------------------------+
| Parameters (dynamic per mode) |
| Offset: [spinner] mm |
| Angle: [spinner] deg |
| Position: [spinner] 0-1 |
| X/Y/Z: [spinner] mm |
+-------------------------------------+
| Options |
| [ ] Link to Spreadsheet |
| [x] Add to Active Body |
| [ ] Custom Name: [text] |
+-------------------------------------+
| [OK] [Cancel] |
+-------------------------------------+
Selection table
Three columns: type icon (28px), element name (stretch), remove button (28px). Duplicates are rejected. A FreeCAD SelectionObserver keeps the "Add Selected" button state synchronized with the active 3D selection.
Mode override
The dropdown lists all 16 modes prefixed by category ([P] plane, [A] axis, [Pt] point). Selecting a mode disables auto-detection until "(Auto-detect)" is re-selected.
Parameters section
Rebuilt dynamically when the mode changes. Only the parameter widgets relevant to the active mode are shown. Modes with no parameters hide the section entirely.
Options
- Link to Spreadsheet: creates a spreadsheet alias and expression-links the datum parameter (offset, angle, coordinates) for parametric control.
- Add to Active Body: when checked, creates a
PartDesign::Plane/Line/Pointinside the active body. When unchecked, creates a document-levelPart::Plane/Line/Vertex. - Custom Name: overrides the auto-generated name (format:
ZPlane_Offset_001).
Dispatch to core.py
DatumCreatorTaskPanel.accept() calls create_datum(), which:
- Reads the current mode, body, name, and parameters from the UI
- Extracts
SelectionItemobjects by type - Dispatches to the corresponding
core.*function:
| Mode | Core function |
|---|---|
offset_face |
core.plane_offset_from_face(face, distance, ...) |
offset_plane |
core.plane_offset_from_plane(plane, distance, ...) |
midplane |
core.plane_midplane(face1, face2, ...) |
3_points |
core.plane_from_3_points(p1, p2, p3, ...) |
normal_edge |
core.plane_normal_to_edge(edge, parameter, ...) |
angled |
core.plane_angled(face, edge, angle, ...) |
tangent_cyl |
core.plane_tangent_to_cylinder(face, angle, ...) |
axis_2pt |
core.axis_from_2_points(p1, p2, ...) |
axis_edge |
core.axis_from_edge(edge, ...) |
axis_cyl |
core.axis_cylinder_center(face, ...) |
axis_intersect |
core.axis_intersection_planes(plane1, plane2, ...) |
point_vertex |
core.point_at_vertex(vertex, ...) |
point_xyz |
core.point_at_coordinates(x, y, z, ...) |
point_edge |
core.point_on_edge(edge, parameter, ...) |
point_face |
core.point_center_of_face(face, ...) |
point_circle |
core.point_center_of_circle(edge, ...) |
Core Implementation
Each core.* function:
- Creates the FreeCAD object (
PartDesign::Planein a body,Part::Planeat document level) - Computes the placement from the source geometry
- Configures attachment (MapMode, AttachmentSupport, offset) for parametric updates
- Stores ZTools metadata in custom properties:
ZTools_Type-- creation method identifier (e.g."offset_from_face")ZTools_Params-- parameters as JSON (e.g.{"distance": 10})ZTools_SourceRefs-- source geometry references as JSON
- Applies Catppuccin Mocha styling (mauve at 70% transparency for planes)
- Optionally links parameters to a spreadsheet alias
Auto-naming uses the format ZPlane_Offset_001, incrementing the index for each new datum of the same type.