ANYgeometry 0.2.2__tar.gz → 0.2.4__tar.gz

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.
Files changed (73) hide show
  1. {anygeometry-0.2.2/src/ANYgeometry.egg-info → anygeometry-0.2.4}/PKG-INFO +38 -2
  2. {anygeometry-0.2.2 → anygeometry-0.2.4}/README.md +37 -1
  3. {anygeometry-0.2.2 → anygeometry-0.2.4}/pyproject.toml +2 -2
  4. {anygeometry-0.2.2 → anygeometry-0.2.4/src/ANYgeometry.egg-info}/PKG-INFO +38 -2
  5. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/ANYgeometry.egg-info/SOURCES.txt +4 -0
  6. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/__init__.py +17 -1
  7. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/editing.py +330 -111
  8. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/features.py +716 -0
  9. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/intersections.py +112 -21
  10. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/model.py +50 -4
  11. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/operations.py +36 -10
  12. anygeometry-0.2.4/src/anygeometry/transforms.py +195 -0
  13. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_features_editing.py +155 -10
  14. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_import_boundaries_cli.py +10 -6
  15. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_intersections.py +16 -0
  16. anygeometry-0.2.4/tests/test_oriented_sheet_owner_api.py +97 -0
  17. anygeometry-0.2.4/tests/test_structural_owner_contracts.py +169 -0
  18. anygeometry-0.2.4/tests/test_transform_pattern_api.py +329 -0
  19. {anygeometry-0.2.2 → anygeometry-0.2.4}/LICENSE +0 -0
  20. {anygeometry-0.2.2 → anygeometry-0.2.4}/setup.cfg +0 -0
  21. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/ANYgeometry.egg-info/dependency_links.txt +0 -0
  22. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/ANYgeometry.egg-info/entry_points.txt +0 -0
  23. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/ANYgeometry.egg-info/requires.txt +0 -0
  24. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/ANYgeometry.egg-info/top_level.txt +0 -0
  25. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/__main__.py +0 -0
  26. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/audit.py +0 -0
  27. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/chains.py +0 -0
  28. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/closure.py +0 -0
  29. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/curves.py +0 -0
  30. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/entities.py +0 -0
  31. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/errors.py +0 -0
  32. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/evaluation.py +0 -0
  33. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/generators/__init__.py +0 -0
  34. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/generators/layout.py +0 -0
  35. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/generators/structural.py +0 -0
  36. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/identity.py +0 -0
  37. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/overlaps.py +0 -0
  38. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/policies.py +0 -0
  39. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/predicates.py +0 -0
  40. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/py.typed +0 -0
  41. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/serialization.py +0 -0
  42. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/sketch.py +0 -0
  43. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/spatial.py +0 -0
  44. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/strict_audit.py +0 -0
  45. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/structural.py +0 -0
  46. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/surfaces.py +0 -0
  47. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/tolerance.py +0 -0
  48. {anygeometry-0.2.2 → anygeometry-0.2.4}/src/anygeometry/transactions.py +0 -0
  49. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_audit.py +0 -0
  50. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_boundary_curve_connect.py +0 -0
  51. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_changed_region_and_indexed_queries.py +0 -0
  52. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_coons_validation_portability.py +0 -0
  53. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_curved_split_contract.py +0 -0
  54. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_editing_gap_closure.py +0 -0
  55. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_generators.py +0 -0
  56. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_identity_topology.py +0 -0
  57. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_intersection_workflow.py +0 -0
  58. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_kernel_identity_structural.py +0 -0
  59. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_local_structural_validation.py +0 -0
  60. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_measurements_complete.py +0 -0
  61. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_mesher_model_contract.py +0 -0
  62. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_model_kernel_update.py +0 -0
  63. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_plate_overlaps.py +0 -0
  64. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_predicates.py +0 -0
  65. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_serialization.py +0 -0
  66. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_serialization_gap_closure.py +0 -0
  67. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_serialization_v3.py +0 -0
  68. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_sketch_features.py +0 -0
  69. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_spatial.py +0 -0
  70. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_strict_audit.py +0 -0
  71. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_structural_lifecycle.py +0 -0
  72. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_surfaces_operations.py +0 -0
  73. {anygeometry-0.2.2 → anygeometry-0.2.4}/tests/test_unknown_features.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ANYgeometry
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: Lightweight deterministic structural-surface geometry kernel
5
5
  Author-email: Audun Arnesen Nyhus <audunarn@gmail.com>
6
6
  License-Expression: GPL-3.0-or-later
@@ -201,6 +201,16 @@ and circular patterns, mirroring, edge/face reversal, deep `clone`, and typed
201
201
  groups, tags, surfaces, holes, and metadata, and deliberately does not weld
202
202
  coincident entities.
203
203
 
204
+ `AffineTransform` provides validated translation, axis-angle rotation, scale,
205
+ reflection, composition, inverse, and point-array evaluation. In-place
206
+ `translate_entities` / `rotate_entities` preserve model-bound identities;
207
+ `copy_translated` / `copy_rotated` allocate fresh identities. Arbitrary
208
+ transform lists use `pattern_entities`, while `rectangular_pattern` creates a
209
+ deterministic one-, two-, or three-axis Cartesian array. Rectangular counts are
210
+ copy steps beyond the unchanged original, so counts `(1, 1)` produce the other
211
+ three positions of a 2x2 array. Pattern implementations extract the selected
212
+ geometry and structural closure once rather than cloning unrelated model data.
213
+
204
214
  ## Serialization and CLI
205
215
 
206
216
  Geometry schema 4 is deterministic and checksummed. It preserves model UUID
@@ -233,12 +243,38 @@ Consumers that require a qualified handoff must retain or rerun
233
243
  JSON and gzip-compressed JSON are supported. Mesh and FEM/project
234
244
  serialization remain outside ANYgeometry.
235
245
 
236
- ANYgeometry 0.2.1 reads schemas 1–4 and writes schema 4. The Python API remains
246
+ ANYgeometry 0.2.4 reads schemas 1–4 and writes schema 4. The Python API remains
237
247
  within `ANYgeometry>=0.2,<0.3`, but a 0.2.0 reader intentionally rejects a
238
248
  schema-4 document. Downstream packages should use the public codecs rather
239
249
  than parse schema records. Legacy relationship evidence migrates as
240
250
  `UNVERIFIED` and never implies exactness or certification.
241
251
 
252
+ Trusted importers and local script features that have already materialized
253
+ topology through `GeometryModel` operations can bind that exact last-good
254
+ materialization without mutating detached feature records:
255
+
256
+ ```python
257
+ geometry.features.adopt_frozen(
258
+ geometry,
259
+ kind="vendor.script.feature",
260
+ outputs={"face": EntityRef("face", face_id)},
261
+ )
262
+ ```
263
+
264
+ `adopt_frozen` accepts only active IDs in the history's owning model; it never
265
+ retargets through replacement lineage or geometric proximity. ANYgeometry
266
+ computes the closure checksum and publishes the history update atomically.
267
+ Callers that already certified a closure may pass `expected_checksum=` to make
268
+ the adoption fail closed if the topology changed.
269
+
270
+ Feature edits mark the affected record dirty. For additive modelling features,
271
+ regeneration starts at the earliest dirty record on a clone of the live
272
+ materialization. The clean prefix keeps its exact entity IDs. A replayed output
273
+ keeps its prior binding only when its stable output-key set and complete
274
+ ID-independent topology closure are exactly equal; otherwise its replacement is
275
+ allocated above the previous ID high-water mark and lineage is extended. This
276
+ comparison uses no distance, tolerance, or nearest-geometry retargeting.
277
+
242
278
  Ordinary output revalidates complete topological and structural integrity.
243
279
  Certified output adds the full global geometric audit before writing, but the
244
280
  ordinary and certified schema-4 payload shapes are identical. Feature history is
@@ -182,6 +182,16 @@ and circular patterns, mirroring, edge/face reversal, deep `clone`, and typed
182
182
  groups, tags, surfaces, holes, and metadata, and deliberately does not weld
183
183
  coincident entities.
184
184
 
185
+ `AffineTransform` provides validated translation, axis-angle rotation, scale,
186
+ reflection, composition, inverse, and point-array evaluation. In-place
187
+ `translate_entities` / `rotate_entities` preserve model-bound identities;
188
+ `copy_translated` / `copy_rotated` allocate fresh identities. Arbitrary
189
+ transform lists use `pattern_entities`, while `rectangular_pattern` creates a
190
+ deterministic one-, two-, or three-axis Cartesian array. Rectangular counts are
191
+ copy steps beyond the unchanged original, so counts `(1, 1)` produce the other
192
+ three positions of a 2x2 array. Pattern implementations extract the selected
193
+ geometry and structural closure once rather than cloning unrelated model data.
194
+
185
195
  ## Serialization and CLI
186
196
 
187
197
  Geometry schema 4 is deterministic and checksummed. It preserves model UUID
@@ -214,12 +224,38 @@ Consumers that require a qualified handoff must retain or rerun
214
224
  JSON and gzip-compressed JSON are supported. Mesh and FEM/project
215
225
  serialization remain outside ANYgeometry.
216
226
 
217
- ANYgeometry 0.2.1 reads schemas 1–4 and writes schema 4. The Python API remains
227
+ ANYgeometry 0.2.4 reads schemas 1–4 and writes schema 4. The Python API remains
218
228
  within `ANYgeometry>=0.2,<0.3`, but a 0.2.0 reader intentionally rejects a
219
229
  schema-4 document. Downstream packages should use the public codecs rather
220
230
  than parse schema records. Legacy relationship evidence migrates as
221
231
  `UNVERIFIED` and never implies exactness or certification.
222
232
 
233
+ Trusted importers and local script features that have already materialized
234
+ topology through `GeometryModel` operations can bind that exact last-good
235
+ materialization without mutating detached feature records:
236
+
237
+ ```python
238
+ geometry.features.adopt_frozen(
239
+ geometry,
240
+ kind="vendor.script.feature",
241
+ outputs={"face": EntityRef("face", face_id)},
242
+ )
243
+ ```
244
+
245
+ `adopt_frozen` accepts only active IDs in the history's owning model; it never
246
+ retargets through replacement lineage or geometric proximity. ANYgeometry
247
+ computes the closure checksum and publishes the history update atomically.
248
+ Callers that already certified a closure may pass `expected_checksum=` to make
249
+ the adoption fail closed if the topology changed.
250
+
251
+ Feature edits mark the affected record dirty. For additive modelling features,
252
+ regeneration starts at the earliest dirty record on a clone of the live
253
+ materialization. The clean prefix keeps its exact entity IDs. A replayed output
254
+ keeps its prior binding only when its stable output-key set and complete
255
+ ID-independent topology closure are exactly equal; otherwise its replacement is
256
+ allocated above the previous ID high-water mark and lineage is extended. This
257
+ comparison uses no distance, tolerance, or nearest-geometry retargeting.
258
+
223
259
  Ordinary output revalidates complete topological and structural integrity.
224
260
  Certified output adds the full global geometric audit before writing, but the
225
261
  ordinary and certified schema-4 payload shapes are identical. Feature history is
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ANYgeometry"
7
- version = "0.2.2"
7
+ version = "0.2.4"
8
8
  description = "Lightweight deterministic structural-surface geometry kernel"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -34,4 +34,4 @@ anygeometry = ["py.typed"]
34
34
  testpaths = ["tests"]
35
35
  python_files = ["test_*.py"]
36
36
  pythonpath = ["src"]
37
- addopts = ["-ra", "-p", "no:cacheprovider", "--basetemp=.pytest_tmp"]
37
+ addopts = ["-ra", "-p", "no:cacheprovider"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ANYgeometry
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: Lightweight deterministic structural-surface geometry kernel
5
5
  Author-email: Audun Arnesen Nyhus <audunarn@gmail.com>
6
6
  License-Expression: GPL-3.0-or-later
@@ -201,6 +201,16 @@ and circular patterns, mirroring, edge/face reversal, deep `clone`, and typed
201
201
  groups, tags, surfaces, holes, and metadata, and deliberately does not weld
202
202
  coincident entities.
203
203
 
204
+ `AffineTransform` provides validated translation, axis-angle rotation, scale,
205
+ reflection, composition, inverse, and point-array evaluation. In-place
206
+ `translate_entities` / `rotate_entities` preserve model-bound identities;
207
+ `copy_translated` / `copy_rotated` allocate fresh identities. Arbitrary
208
+ transform lists use `pattern_entities`, while `rectangular_pattern` creates a
209
+ deterministic one-, two-, or three-axis Cartesian array. Rectangular counts are
210
+ copy steps beyond the unchanged original, so counts `(1, 1)` produce the other
211
+ three positions of a 2x2 array. Pattern implementations extract the selected
212
+ geometry and structural closure once rather than cloning unrelated model data.
213
+
204
214
  ## Serialization and CLI
205
215
 
206
216
  Geometry schema 4 is deterministic and checksummed. It preserves model UUID
@@ -233,12 +243,38 @@ Consumers that require a qualified handoff must retain or rerun
233
243
  JSON and gzip-compressed JSON are supported. Mesh and FEM/project
234
244
  serialization remain outside ANYgeometry.
235
245
 
236
- ANYgeometry 0.2.1 reads schemas 1–4 and writes schema 4. The Python API remains
246
+ ANYgeometry 0.2.4 reads schemas 1–4 and writes schema 4. The Python API remains
237
247
  within `ANYgeometry>=0.2,<0.3`, but a 0.2.0 reader intentionally rejects a
238
248
  schema-4 document. Downstream packages should use the public codecs rather
239
249
  than parse schema records. Legacy relationship evidence migrates as
240
250
  `UNVERIFIED` and never implies exactness or certification.
241
251
 
252
+ Trusted importers and local script features that have already materialized
253
+ topology through `GeometryModel` operations can bind that exact last-good
254
+ materialization without mutating detached feature records:
255
+
256
+ ```python
257
+ geometry.features.adopt_frozen(
258
+ geometry,
259
+ kind="vendor.script.feature",
260
+ outputs={"face": EntityRef("face", face_id)},
261
+ )
262
+ ```
263
+
264
+ `adopt_frozen` accepts only active IDs in the history's owning model; it never
265
+ retargets through replacement lineage or geometric proximity. ANYgeometry
266
+ computes the closure checksum and publishes the history update atomically.
267
+ Callers that already certified a closure may pass `expected_checksum=` to make
268
+ the adoption fail closed if the topology changed.
269
+
270
+ Feature edits mark the affected record dirty. For additive modelling features,
271
+ regeneration starts at the earliest dirty record on a clone of the live
272
+ materialization. The clean prefix keeps its exact entity IDs. A replayed output
273
+ keeps its prior binding only when its stable output-key set and complete
274
+ ID-independent topology closure are exactly equal; otherwise its replacement is
275
+ allocated above the previous ID high-water mark and lineage is extended. This
276
+ comparison uses no distance, tolerance, or nearest-geometry retargeting.
277
+
242
278
  Ordinary output revalidates complete topological and structural integrity.
243
279
  Certified output adds the full global geometric audit before writing, but the
244
280
  ordinary and certified schema-4 payload shapes are identical. Feature history is
@@ -34,6 +34,7 @@ src/anygeometry/structural.py
34
34
  src/anygeometry/surfaces.py
35
35
  src/anygeometry/tolerance.py
36
36
  src/anygeometry/transactions.py
37
+ src/anygeometry/transforms.py
37
38
  src/anygeometry/generators/__init__.py
38
39
  src/anygeometry/generators/layout.py
39
40
  src/anygeometry/generators/structural.py
@@ -54,6 +55,7 @@ tests/test_local_structural_validation.py
54
55
  tests/test_measurements_complete.py
55
56
  tests/test_mesher_model_contract.py
56
57
  tests/test_model_kernel_update.py
58
+ tests/test_oriented_sheet_owner_api.py
57
59
  tests/test_plate_overlaps.py
58
60
  tests/test_predicates.py
59
61
  tests/test_serialization.py
@@ -63,5 +65,7 @@ tests/test_sketch_features.py
63
65
  tests/test_spatial.py
64
66
  tests/test_strict_audit.py
65
67
  tests/test_structural_lifecycle.py
68
+ tests/test_structural_owner_contracts.py
66
69
  tests/test_surfaces_operations.py
70
+ tests/test_transform_pattern_api.py
67
71
  tests/test_unknown_features.py
@@ -9,12 +9,19 @@ from .editing import (
9
9
  PatternResult,
10
10
  circular_pattern,
11
11
  copy_entities,
12
+ copy_rotated,
13
+ copy_translated,
12
14
  insert_model,
13
15
  linear_pattern,
14
16
  measure,
15
17
  mirror_entities,
18
+ move_entities,
19
+ pattern_entities,
20
+ rectangular_pattern,
16
21
  reverse_edge,
17
22
  reverse_face,
23
+ rotate_entities,
24
+ translate_entities,
18
25
  )
19
26
  from .errors import GeometryError, GeometryTopologyError
20
27
  from .evaluation import (
@@ -61,6 +68,7 @@ from .model import GeometryModel
61
68
  from .identity import EntityHandle, Resolution, ResolutionStatus
62
69
  from .transactions import AABBChange, ChangeSet, TopologyTransaction
63
70
  from .tolerance import DEFAULT_TOLERANCE_POLICY, TolerancePolicy, feature_extent
71
+ from .transforms import AffineTransform
64
72
  from .predicates import (
65
73
  IntersectionComponent,
66
74
  IntersectionDimension,
@@ -164,6 +172,7 @@ __all__ = [
164
172
  "AABB",
165
173
  "AABBChange",
166
174
  "AABBTree",
175
+ "AffineTransform",
167
176
  "Arc",
168
177
  "ArcFrame",
169
178
  "Attachment",
@@ -263,6 +272,8 @@ __all__ = [
263
272
  "clip_line_to_face",
264
273
  "closest_uv",
265
274
  "copy_entities",
275
+ "copy_rotated",
276
+ "copy_translated",
266
277
  "circular_pattern",
267
278
  "edge_tangent_many",
268
279
  "evaluate_edge_many",
@@ -291,7 +302,9 @@ __all__ = [
291
302
  "measure",
292
303
  "materialize_sketch",
293
304
  "mirror_entities",
305
+ "move_entities",
294
306
  "numerical_surface_intersection",
307
+ "pattern_entities",
295
308
  "plane_cylinder",
296
309
  "plane_plane",
297
310
  "plan_imprint",
@@ -300,8 +313,10 @@ __all__ = [
300
313
  "project_to_face_many",
301
314
  "punch_hole",
302
315
  "read_geometry",
316
+ "rectangular_pattern",
303
317
  "reverse_edge",
304
318
  "reverse_face",
319
+ "rotate_entities",
305
320
  "split_face",
306
321
  "split_face_at",
307
322
  "split_face_between",
@@ -312,6 +327,7 @@ __all__ = [
312
327
  "surface_point",
313
328
  "to_dict",
314
329
  "transform",
330
+ "translate_entities",
315
331
  "trim_face",
316
332
  "write_geometry",
317
333
  "builtin_feature_registry",
@@ -321,4 +337,4 @@ __all__ = [
321
337
  "JunctionMemberUse",
322
338
  ]
323
339
 
324
- __version__ = "0.2.2"
340
+ __version__ = "0.2.4"