Feature declarations¶
These constructors create Draftwright IR features from build123d objects or explicit values.
They are useful when supplying a declared PartModel; most applications should prefer the
corresponding Sheet verbs.
hole(obj=None, *, diameter=None, at=None, axis=None, through=True, depth=None, cbore=None, spotface=None, csink=None, thread=None, count=1, members=())
¶
A drilled hole. Either hole(tool_cylinder) — read ⌀ / axis / location off the
build123d object you subtracted — or hole(diameter=6, at=(20, 10, 0), axis="z").
cbore / spotface are (diameter, depth) pairs; csink is a
(major_diameter, included_angle) pair (a flat-head seat, callout ⌵ Ø.. × ..°);
thread is a tap/thread spec string (e.g. "M3x0.5") folded onto the callout
(#764); count + members describe a machining-spec group drawn as one count×.
An object supplies defaults; any explicit keyword overrides that field (#451).
double_d_bore(obj=None, *, major_diameter=None, across_flats=None, at=None, axis=None, depth=None, through=True, profile_direction=None)
¶
A through double-D bore, from its cutter or explicit geometric values.
major_diameter is the diameter of the parent circle and across_flats is the
distance between its two parallel chords. The object form accepts an extruded cutter
with exactly that boundary; arbitrary line/arc profiles and blind profiles fail closed.
boss(obj=None, *, diameter=None, height=None, at=None, axis=None, span=None, thread=None)
¶
An external cylindrical boss / OD. Either boss(cylinder) or
boss(diameter=6, at=(0, 0, 0), axis="x") (parametric). An object supplies
defaults; any explicit keyword overrides that field (#451).
polygonal_boss(*, side_count, across_flats, height, at, axis, flat_directions, flat_centres, span=None)
¶
A declared regular polygonal-prism boss, sized across flats and by height.
This explicit form carries the physical side-face directions and anchor points used by placement. Geometry-object inference is deliberately absent: a detached prism does not prove that it is an attached boss, while an author calling this verb does.
step(obj=None, *, diameter=None, length=None, at=None, axis=None, span=None, thread=None)
¶
One axial segment of a turned profile — its OD + length. Either step(segment)
(⌀ from the cylindrical face, length + centre from the bbox along its axis) or
explicit step(diameter=4, length=10, at=(0, 0, 0), axis="x"). span (the two
axial end-points) is derived from at + length when not given. An object supplies
defaults; any explicit keyword overrides that field (#451).
chamfer(obj=None, *, axis=None, leg=None, leg1=None, leg2=None, angle=None, at=None)
¶
A chamfer (bevelled edge, #560/#576). Either chamfer(bevel_face) — the oblique
chamfer face supplies axis, both legs and a leader point on the bevel — or explicit
chamfer(axis="z", leg=6, at=(x, y, z)). leg is an equal-leg 45° chamfer (callout
C{leg}); give both leg1/leg2 for an asymmetric one ({leg} × {angle}°).
The angle is always derived from the legs; an explicit angle= is only validated
against them (a one-leg-plus-angle spec is not yet supported — #581). An object supplies
defaults; any explicit keyword overrides (#451).
fillet(obj=None, *, axis=None, radius=None, at=None)
¶
A fillet (rounded edge, #561). Either fillet(round_face) — the cylindrical blend
face supplies axis, radius and a leader point on the round — or explicit
fillet(axis="z", radius=3, at=(x, y, z)). Called out R{radius} (grouped n× R
for equal radii). An object supplies defaults; any explicit keyword overrides (#451).
flat(obj=None, *, axis=None, across=None, at=None, axis_line=None, stock_span=None, axis_direction=None)
¶
A machined flat on round stock (#148b). Either flat(flat_face) — the planar face
supplies the leader point at (axis= and across= still required, being
unrecoverable from a plane) — or fully explicit flat(axis="z", across=15, at=(x, y,
z)). axis_direction= carries a non-principal stock direction; axis_line= and
stock_span= then complete its geometric identity. Called out {across} A/F (across
flats). An object supplies the at default; any explicit keyword overrides (#451).
groove(obj=None, *, axis=None, width=None, diameter=None, at=None)
¶
A turned / circlip groove on round stock (#148c). Either groove(floor_face) — the
reduced-OD floor face supplies axis, width, diameter and the leader point at — or
fully explicit groove(axis="z", width=3, diameter=16, at=(x, y, z)). Called out
{width} WIDE × ø{diameter}. An object supplies defaults; any explicit keyword
overrides (#451).
rotational(*, od, bores=(), at=None, axis=None)
¶
A turned body's axial furniture — its outer diameter, rotation axis and concentric
bores (#945). Explicit values only: rotational(od=30, bores=(16,), axis="z").
The last recognised kind with no declarative surface, which made it the last ADR 0011
round-trip gap (epic #574). Its absence was load-bearing rather than cosmetic: a
RotationalFeature carries planned dimensions (od, each bore), so a generated script
could not name them, and the dimension mirror fell back to auto_dimensions() for the
whole part — one unsupported feature turning every other declaration in that script from
explicit back to implicit (#938).
There is deliberately no object form, unlike every sibling verb — the signature is
keyword-only so rotational(shaft) is rejected by Python rather than accepted and then
guessed at. An object form would have to re-derive the OD, the axis AND the concentric
bores from geometry, and detection does not read those off the solid: they come from the
part CLASSIFICATION (analysis._classify_geometry / _sizing_bores), which also decides
which concentric bores are sizing bores. A declare-side reimplementation would be a second
inference path for one fact, and the first cut proved the point — it silently dropped
every bore and picked the wrong axis for a cylinder as long as it is wide (#949 review).
A convenient object form that quietly changes the drawing is worse than an explicit one.
Restoring it needs the classification factored into something both sides call — #950.
bores are concentric bore diameters in display order, each placed as a centred leader,
and are Z-axis only — a rule :class:~draftwright.model.ir.RotationalFeature owns and
states, since every route into the IR needs it. at is a point on the rotation axis
(default the origin); it is carried for round-trip identity and does not itself position
the furniture, which the renderer places from the part's projected centre (#952).
plate(obj=None, *, axis=None, lo=None, hi=None, u=None, v=None)
¶
A thin slab's thickness (#559/#577) — a base plate, an upright wall, a rib. Either
plate(slab_box) — the thin axis, its lo/hi extent, and the u/v slab
centre read off the object's bbox — or explicit plate(axis="z", lo=0, hi=4, u=10, v=5).
hi - lo is the thickness; u/v locate the thickness dim on the other two axes
(in axis order). An object supplies defaults; any explicit keyword overrides (#451).
step_level(obj=None, *, base=None, levels=None, shoulders=None, datum=None, at=None, level_supports=None)
¶
A prismatic height ladder + step-position shoulders (#555/#578) — a rebated / stepped
block. Either step_level(part) — base, the interior levels, the (axis,
position) shoulders, the datum and the frame anchor at read off the part — or
explicit step_level(base=0, levels=(10,), shoulders=(("x", 30),)). levels are the
interior step Z-coords (unique, strictly increasing, each above base); a shoulder is
where a step changes height, its position measured from datum along a horizontal
axis (x/y). at is the IR frame origin (like every sibling constructor); it defaults
to the datum X/Y at base and is inert for step rendering. level_supports may
carry one (level, x_span, y_span) record per level so a dimension retains the face that
established it (#915). An object supplies defaults; any explicit keyword overrides that
field (#451).
slot(obj=None, *, width=None, length=None, long_axis=None, width_axis=None, depth_axis=None, w_center=None, lo=None, hi=None, at=None)
¶
A milled slot / reduced across-flats section. From an object the depth (through, not
stored) axis defaults to the shortest bbox span; the two remaining axes are read as
long_axis (the longer) / width_axis (the shorter). lo/hi are the extent along the
long axis and w_center the centre across the width axis. An object supplies defaults;
any explicit keyword overrides that field (#451).
Pass depth_axis= when the cutter's through span is not the shortest — a through-Z
milled slot cut by a tall cutter has Z as its longest span, so the shortest-span default
would mistake Z for the long axis (#490). Naming the depth axis excludes it, so long/width
are read from the two in-plane axes.
pocket(obj=None, *, width=None, length=None, depth=None, long_axis=None, width_axis=None, depth_axis=None, w_center=None, lo=None, hi=None, at=None, edge_anchored=False)
¶
A blind rectangular recess — a floored slot/pocket, dimensioned width × length ×
depth (#148a). The blind counterpart of :func:slot: unlike a through-slot the depth
IS a stored size, read from the object's span along the depth_axis. From an object
the depth axis defaults to the shortest bbox span (a shallow recess); the two
remaining axes are long_axis (the longer) / width_axis (the shorter). Pass
depth_axis= when the recess is deeper than it is wide (#490-style). lo/hi are
the extent along the long axis and w_center the centre across the width axis. An
object supplies defaults; any explicit keyword overrides that field.
channel(*, width, long_axis, width_axis, w_center, lo, hi, d_lo, d_hi, open_sign=1, at=None)
¶
A full-span floored channel, dimensioned only by wall-to-wall width.
The longitudinal and depth bounds identify the physical channel and preserve recognition/declaration parity; they are not additional dimensions.
pad(obj=None, *, x0=None, x1=None, y0=None, y1=None, z0=None, z1=None, at=None)
¶
A bounded rectangular raised pad, dimensioned by footprint and location.
pad(pad_solid) reads its axis-aligned bounding box; the explicit flavour
accepts the six bounds used by generated Sheet scripts.
pattern(member, *, kind, count, at=None, axis=None, members=(), bcd=None, pitch=None, direction=None, grid=None, rows=None, cols=None, angle=None)
¶
A hole pattern = count × a member hole (build one with :func:hole). The
arrangement (bolt_circle / linear / grid) and its defining dims (bcd /
pitch / grid + rows/cols/angle) are supplied, not read.
at (the pattern centre) and axis default to the member's frame. The member
centres are computed from the arrangement so the pattern renders like a detected one
(its count× balloon, BCD centreline and pitch dims anchor on members); pass
members= explicitly to override the computed layout (required for kind="other").
pocket_pattern(member, *, kind='linear', count, at=None, members=(), pitch=None, direction=None, grid=None, rows=None, cols=None, angle=None)
¶
count × an identical blind pocket in a linear / grid array (#841) — the
recess analog of :func:pattern. member is one representative pocket (build it with
:func:pocket); the array renders as ONE grouped N× W × L × D DEEP callout plus the
(n-1)× pitch dim(s), instead of N competing size dims.
The arrangement lies in the pocket's OPENING plane (perpendicular to its depth axis), so
the members are laid out about at (default the member's own centre) in that plane —
pass members= to override the computed layout. pitch (linear) / grid +
rows/cols (grid) define the spacing and are read by the pitch-dim furniture.
slot_pattern(member, *, kind='linear', count, at=None, members=(), pitch=None, direction=None, grid=None, rows=None, cols=None, angle=None)
¶
count × an identical milled slot in a linear / grid array (#841) — the
through-slot analog of :func:pocket_pattern. member is one representative slot (build it
with :func:slot); the array renders as ONE grouped N× SLOT W × L leader plus the
(n-1)× pitch dim(s), instead of N competing size dims (some of which drop for lack of
room, #841 behaviour 1).
A slot has no depth, so the array lies in the face plane perpendicular to the slot's THROUGH
axis (the one that is neither width nor long). Members are laid out about at (default the
member's own centre) in that plane; pitch (linear) / grid + rows/cols (grid)
define the spacing. Explicit members= is rejected — the computed layout is the truthful
one (see :func:pocket_pattern).
envelope(obj)
¶
The overall bounding box of obj as width (X) / height (Z) / depth (Y), matching the detector's prismatic envelope.
Measured on the SOLIDS, not on obj as handed in. An AP242 STEP import is a compound of the part plus its PMI presentation geometry — annotation planes, leader curves — and measuring the whole thing declared CTC01 as 1170 × 650 where the part is 800 × 450: an envelope 370 mm too wide, silently, in anything a user declared by hand (#977).
The frame origin is the bbox CENTRE, matching detect.py — it was bb.min.Z, so a
hand-declared envelope sat a half-height below a detected one on the same part. Invisible
through the emitter, which bakes the detected frame explicitly, and therefore only ever
wrong for someone writing sheet.envelope() themselves — which is what the README shows.
The same shape of defect as the measurement above: this verb claimed to match the detector
and did not (#977).
_solids_body is the engine's existing answer to that, already used by _analyse and
Sheet.model so a caller inspects the body the engine draws (#453). Sharing it is what
makes the docstring's "matching the detector's" claim true rather than aspirational; the
detected path was always right, and it is this declared verb that was measuring the file.
datum(letter, ref, part=None, *, view=None, side=None)
¶
A datum feature symbol (ISO 5459) on ref — a feature or a planar face (ADR 0011 P2c).
finish(ra, ref, part=None, *, view=None, side=None)
¶
A surface-finish symbol (ISO 1302, Ra) on ref — a feature or a planar face (P2c).
note(text, ref, part=None, *, view=None, side=None)
¶
A free-text manufacturing note (#488) on a leader to ref — a feature or a planar face
(ADR 0011 P2c). The shop callouts detection can't infer: thread specs (M3x0.5 TAP),
DEBURR, chip-relief, knurl. Placed like the GD&T items (a first-class ADR 0009 corridor
candidate), not the dimension planner.
control_frame(characteristic, tolerance, ref, part=None, *, datums=(), diameter=False, modifier=None, view=None, side=None)
¶
A geometric-tolerance feature control frame (ISO 1101) on ref — a feature or a planar
face (ADR 0011 P2c.2). characteristic is a lowercase ISO 1101 name ("position" …);
datums the referenced datum letters; diameter prefixes the zone with ⌀; modifier
a material-condition symbol ("M"/"L"/"P").
measured_dimension(*, kind, value, label, dominant_axis, ref_pts, ref_bbox=None, at=None, axis=None, upper_tol=None, lower_tol=None, lower_bound=None, upper_bound=None, source='sheet', source_kind=None, source_id='')
¶
A pre-authored drafting dimension from explicit measured values — the IR constructor
behind :meth:Sheet.measured_dimension (#704: extracted so build_drawing(model=…)
callers can author one without the façade). Validates the kind against
:data:~draftwright.model.ir.AUTHORED_DIMENSION_KINDS, needs ≥2 ref_pts, and derives
at (the ref_bbox centre, else the ref_pts centroid) when not given.
lower_bound and upper_bound carry a limit range and must be supplied together; they
are mutually exclusive with deviation tolerances. source_id preserves an external
record identity; ordinary Sheet declarations leave it blank.