b123d-recognisers 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,209 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2024-2026 Paul Fremantle
3
+ """Deterministic geometry-only feature recognition for build123d solids.
4
+
5
+ This Apache-2.0 package is the single recognition implementation shared by consumers. Import the
6
+ public surface from here, not the implementation submodules.
7
+
8
+ Recogniser contract (ADR 0002)
9
+ ------------------------------
10
+ A *feature* recogniser takes one of two shapes:
11
+
12
+ - **Part-based** — ``recognise_<feature>(part, *, <tuning / injected deps>) -> list[record]``
13
+ (``recognise_holes(part, *, cyls=None)``, ``recognise_chamfers(part, *, tol=...)``,
14
+ ``recognise_risers(part, *, tol=...)``). Everything after ``part`` is
15
+ **keyword-only** — both tuning and any injected inventory. A recogniser **never
16
+ re-recognises a dependency internally**; the orchestration caller owns the single inventory
17
+ and threads it.
18
+ - **Derived** — ``recognise_<feature>(inventory) -> list[record]``
19
+ (``recognise_hole_patterns(holes)``):
20
+ operates purely on another recogniser's records, no ``part`` and no tuning, so the
21
+ single inventory arg is unambiguous and stays positional.
22
+
23
+ Common to both: a **British** ``recognise_`` verb (not ``find_``/``analyse_``); a
24
+ **deterministic ``list`` of frozen-dataclass records** (empty when absent — never
25
+ ``Optional``-singular, never a bare ``list`` of primitives); **geometry-only records** (no
26
+ build123d types leak out; consumers adapt these values into their own domain models).
27
+
28
+ The contract holds for **every** recogniser, including the two that once strained it —
29
+ their records were simply the wrong shape (#568):
30
+
31
+ - ``recognise_face_levels -> list[FaceLevel]`` (was ``list[float]``) — a level is now a
32
+ ``FaceLevel(z)`` record.
33
+ - ``recognise_turned_steps -> list[TurnedStep]`` (was ``TurnedProfile | None``) — each
34
+ ``TurnedStep`` now carries its ``axis``, so it is a self-contained record and the old
35
+ ``TurnedProfile`` wrapper is no longer the return. ``TurnedProfile`` survives only as a
36
+ **pipeline aggregate** (``TurnedProfile.from_steps``) for consumers that want axis +
37
+ shoulders as a unit — it is not a recogniser return.
38
+
39
+ Record class names avoid consumer-domain ``Feature`` types: for example, the public records are
40
+ ``HoleRecord`` and ``BossRecord`` rather than drawing or manufacturing IR types.
41
+
42
+ ``analyse_cylinders`` / ``full_cylinders`` / ``feature_diameters`` are **not** recognisers
43
+ under this contract — they are cylinder-analysis *substrate* (a tuple of dicts / a diameter
44
+ query), and deliberately keep their names. Likewise the **shared single-face reads**
45
+ (``classify_bevel``/``BevelReject``, ``fillet_anchor``, ``cone_rims``,
46
+ ``floor_face_anchor``, ``step_level_zs``, #704): helpers shared with the declared
47
+ front-end, not recognisers — they traffic in build123d/OCP objects and are exposed only where
48
+ existing Draftwright compatibility requires them.
49
+
50
+ ``project_step_shoulders`` is likewise not a recogniser but its mirror image: a **pure
51
+ projection** over :func:`recognise_risers`' records, with no ``part`` and no geometry access
52
+ at all. It carries the ``project_`` verb rather than ``recognise_`` because the aggregate owns
53
+ the evidence and each consumer projects. A function that cannot look at a solid cannot become a
54
+ second recognition site.
55
+ """
56
+
57
+ from __future__ import annotations
58
+
59
+ from importlib.metadata import PackageNotFoundError, version
60
+
61
+ from b123d_recognisers._features import (
62
+ BoltCircle,
63
+ BossRecord,
64
+ CounterBore,
65
+ HoleRecord,
66
+ HoleSpec,
67
+ LinearArray,
68
+ RectGrid,
69
+ analyse_cylinders,
70
+ feature_diameters,
71
+ full_cylinders,
72
+ recognise_bosses,
73
+ recognise_hole_patterns,
74
+ recognise_holes,
75
+ )
76
+ from b123d_recognisers.chamfers import (
77
+ BevelReject,
78
+ Chamfer,
79
+ classify_bevel,
80
+ recognise_chamfers,
81
+ )
82
+ from b123d_recognisers.countersinks import (
83
+ CounterSink,
84
+ cone_rims,
85
+ countersink_matches_hole,
86
+ recognise_countersinks,
87
+ )
88
+ from b123d_recognisers.fillets import Fillet, fillet_anchor, recognise_fillets
89
+ from b123d_recognisers.flats import Flat, recognise_flats
90
+ from b123d_recognisers.grooves import Groove, floor_face_anchor, recognise_grooves
91
+ from b123d_recognisers.levels import (
92
+ FaceLevel,
93
+ RiserEvidence,
94
+ StepShoulder,
95
+ project_step_shoulders,
96
+ recognise_face_levels,
97
+ recognise_risers,
98
+ step_level_records,
99
+ step_level_zs,
100
+ )
101
+ from b123d_recognisers.pads import RaisedPad, recognise_rectangular_pads
102
+ from b123d_recognisers.plates import Plate, has_multi_axis_plates, recognise_plates
103
+ from b123d_recognisers.polygonal_bosses import (
104
+ PolygonalBoss,
105
+ PolygonalStock,
106
+ recognise_polygonal_bosses,
107
+ recognise_polygonal_stock,
108
+ )
109
+ from b123d_recognisers.profiled_bores import DoubleDBore, recognise_double_d_bores
110
+ from b123d_recognisers.repeating_profiles import (
111
+ RepeatingRadialProfile,
112
+ recognise_repeating_radial_profiles,
113
+ )
114
+ from b123d_recognisers.result import RecognitionResult, build_recognition_result
115
+ from b123d_recognisers.slots import (
116
+ Channel,
117
+ Pocket,
118
+ PocketArray,
119
+ PocketGrid,
120
+ Slot,
121
+ SlotArray,
122
+ SlotGrid,
123
+ recognise_channels,
124
+ recognise_pocket_patterns,
125
+ recognise_pockets,
126
+ recognise_slot_patterns,
127
+ recognise_slots,
128
+ )
129
+ from b123d_recognisers.turned import TurnedProfile, TurnedStep, recognise_turned_steps
130
+
131
+ try:
132
+ __version__ = version("b123d-recognisers")
133
+ except PackageNotFoundError:
134
+ __version__ = "0.1.0"
135
+
136
+ # Imported after the recognition surface because census consumes that public orchestration.
137
+ from b123d_recognisers.census import feature_census # noqa: E402
138
+
139
+ __all__ = [
140
+ "__version__",
141
+ "BoltCircle",
142
+ "Chamfer",
143
+ "Channel",
144
+ "Fillet",
145
+ "Flat",
146
+ "Groove",
147
+ "BossRecord",
148
+ "CounterBore",
149
+ "CounterSink",
150
+ "countersink_matches_hole",
151
+ "DoubleDBore",
152
+ "FaceLevel",
153
+ "HoleRecord",
154
+ "HoleSpec",
155
+ "LinearArray",
156
+ "Plate",
157
+ "Pocket",
158
+ "PocketArray",
159
+ "PocketGrid",
160
+ "PolygonalBoss",
161
+ "PolygonalStock",
162
+ "RaisedPad",
163
+ "RepeatingRadialProfile",
164
+ "RectGrid",
165
+ "Slot",
166
+ "SlotArray",
167
+ "SlotGrid",
168
+ "RiserEvidence",
169
+ "StepShoulder",
170
+ "TurnedProfile",
171
+ "TurnedStep",
172
+ "RecognitionResult",
173
+ "BevelReject",
174
+ "analyse_cylinders",
175
+ "classify_bevel",
176
+ "cone_rims",
177
+ "fillet_anchor",
178
+ "floor_face_anchor",
179
+ "has_multi_axis_plates",
180
+ "project_step_shoulders",
181
+ "recognise_face_levels",
182
+ "recognise_risers",
183
+ "step_level_records",
184
+ "step_level_zs",
185
+ "feature_diameters",
186
+ "feature_census",
187
+ "recognise_bosses",
188
+ "recognise_chamfers",
189
+ "recognise_channels",
190
+ "recognise_fillets",
191
+ "recognise_flats",
192
+ "recognise_grooves",
193
+ "recognise_countersinks",
194
+ "recognise_double_d_bores",
195
+ "recognise_hole_patterns",
196
+ "recognise_holes",
197
+ "recognise_plates",
198
+ "recognise_pocket_patterns",
199
+ "recognise_pockets",
200
+ "recognise_polygonal_bosses",
201
+ "recognise_polygonal_stock",
202
+ "recognise_rectangular_pads",
203
+ "recognise_repeating_radial_profiles",
204
+ "recognise_slot_patterns",
205
+ "recognise_slots",
206
+ "recognise_turned_steps",
207
+ "build_recognition_result",
208
+ "full_cylinders",
209
+ ]