Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,7 @@ sandbox-envs/
.agents/
.sharednet/
design-docs/

# local, not part of the SDK
examples/workspace/
phase2-contract-review.md
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,31 @@ user-facing notes live in [`docs/updates/`](docs/updates/) (English and

## Unreleased

## 2.2.6.post2 — 2026-10-21

### Changed

- Operators: `scale_rsolid` and `transform_rsolid` are implemented in `operators/transform.py`,
`boolean_rsolidlist` in `operators/boolean.py`, and `offset_rsolid`, `draft_rsolid`,
`extrude_taper_rsolid`, `extrude_until_rsolid` and `sweep_multisection_rsolid` in
`operators/features.py`, next to the operators of their family. `from simplecadapi import ...`
is unchanged. The one-feature modules they were first written in (`operators.deformation`,
`draft`, `section_features`, `limited_extrusion`) remain as aliases: importing a name from
them still works and raises a `DeprecationWarning` that names the new place.

### Fixed

- Skill API docs: the documentation generator listed its source files and public functions by
hand and had never been told about those four modules, so the docs of the eight operators
above were kept by hand and deleted by the generator's clean-up. `operators/` is now
discovered, a function the package exports is public, the content of the hand-written docs
(examples, error conditions, replay notes) is in the docstrings, and tests check that every
public operator has a doc and that the committed docs are exactly what the generator writes.
`boolean_rsolidlist` had no doc at all.
- Skill API docs of `NotebookRun`, `run_notebook` and `add_bspline_rsketch` caught up with the
code (`through`, `product` and `timeout`; a partial run's `product` is `None`; closed
B-splines).

## 2.2.6.post1 — 2026-10-21

### Fixed
Expand Down
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,20 +149,19 @@ the full crank cycle sweeps clean in the same sim ·

---

## Update Notes (2.2.6.post1)
## Update Notes (2.2.6.post2)

> Validate generated definitions, assembly constraints, and manufacturing
> geometry before production use.

- **Keyword `scad.var` is a parameter again.** `scad.var(name="j1", default=0.0)` is read
by the editor's parameter panel like the positional form; before, it was skipped.
- **A cached run costs much less.** On the desktop arm: cold 80 s to 35 s, nothing changed
24 s to 4 s, one joint edited 18 s to 3 s, cache 1.7 GB to 96 MB. Restored shapes are built
on first use, parameters and imported names are keyed by value, and the `use` calls of a
cell run in worker processes (`SCA_JOBS`, 1 turns it off).
- **Slider drags are sent when they settle**, not step by step.
- **Operators live with their family.** `scale_rsolid`, `transform_rsolid`, `boolean_rsolidlist`,
`offset_rsolid`, `draft_rsolid`, `extrude_taper_rsolid`, `extrude_until_rsolid` and
`sweep_multisection_rsolid` moved into `operators/transform.py`, `boolean.py` and `features.py`.
`from simplecadapi import ...` is unchanged; the old module paths warn and still work.
- **Every operator's API reference is generated**, and tests fail when one has no doc or the
committed docs differ from the generator's output.

Full notes for this version: [`docs/updates/2.2.6.post1.md`](docs/updates/2.2.6.post1.md).
Full notes for this version: [`docs/updates/2.2.6.post2.md`](docs/updates/2.2.6.post2.md).
Earlier versions: the [changelog](CHANGELOG.md) and [`docs/updates/`](docs/updates/).

---
Expand All @@ -183,7 +182,7 @@ in a compact public API for creating solids, applying features, tagging semantic
intent, querying topology, exporting manufacturing files, and translating recorded
models into FreeCAD workflows.

Current release: `simplecadapi==2.2.6.post1`.
Current release: `simplecadapi==2.2.6.post2`.

## What It Provides

Expand Down Expand Up @@ -698,6 +697,7 @@ and the [STEP reconstruction workflow](docs/skill/references/workflows/step-reco

## Documentation

- 2.2.6.post2 update notes: [`docs/updates/2.2.6.post2.md`](docs/updates/2.2.6.post2.md)
- 2.2.6.post1 update notes: [`docs/updates/2.2.6.post1.md`](docs/updates/2.2.6.post1.md)
- 2.2.6 update notes: [`docs/updates/2.2.6.md`](docs/updates/2.2.6.md)
- 2.2.5 update notes: [`docs/updates/2.2.5.md`](docs/updates/2.2.5.md)
Expand Down
17 changes: 8 additions & 9 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,18 +133,16 @@ CalculiX 静力 FEM(边界面按保真的 `interface.*` 标签选取,仿真

---

## 更新日志(2.2.6.post1)
## 更新日志(2.2.6.post2)

> 投入生产前请验证生成的定义、装配约束和制造几何。

- **关键字写法的 `scad.var` 重新被识别为参数。** `scad.var(name="j1", default=0.0)` 现在和
位置参数写法一样出现在参数面板;之前会被跳过。
- **缓存运行便宜得多。** 桌面机械臂:冷启动 80 秒到 35 秒,什么都没改 24 秒到 4 秒,改一个关节 18 秒到 3 秒,
缓存 1.7 GB 到 96 MB。形状在第一次用到时才构建,参数和导入的名字按值定键,cell 里的 `use` 调用在 worker
进程里并行(`SCA_JOBS`,设为 1 关闭)。
- **滑块拖动在停下来时才发送**,不再逐步发送。
- **算子放在自己家族的模块里。** `scale_rsolid`、`transform_rsolid`、`boolean_rsolidlist`、`offset_rsolid`、
`draft_rsolid`、`extrude_taper_rsolid`、`extrude_until_rsolid`、`sweep_multisection_rsolid` 搬进了
`operators/transform.py`、`boolean.py`、`features.py`。`from simplecadapi import ...` 用法不变;旧的模块路径仍可用,并会给出警告。
- **每个算子的 API 参考都由生成器生成**,缺文档、或已提交的文档与生成器输出不一致,测试都会失败。

本版本的完整说明:[`docs/updates/2.2.6.post1.zh-CN.md`](docs/updates/2.2.6.post1.zh-CN.md)。
本版本的完整说明:[`docs/updates/2.2.6.post2.zh-CN.md`](docs/updates/2.2.6.post2.zh-CN.md)。
更早的版本:见[更新日志](CHANGELOG.md)和 [`docs/updates/`](docs/updates/)。

---
Expand All @@ -162,7 +160,7 @@ CalculiX 静力 FEM(边界面按保真的 `interface.*` 标签选取,仿真

SimpleCADAPI 是一个基于 OCP 的 Python CAD SDK,提供清晰的函数式建模操作和可重放的模型图。它在 OpenCascade 几何内核之上提供精简的公共 API,可用于创建实体、应用特征、添加语义标签、查询拓扑、导出制造文件,以及将记录的模型转换为 FreeCAD 工作流。

当前版本:`simplecadapi==2.2.6.post1`。
当前版本:`simplecadapi==2.2.6.post2`。

## 核心能力

Expand Down Expand Up @@ -588,6 +586,7 @@ uv run --extra fem python examples/ap242_gmsh_volume_mesh/run_calculix.py

## 文档

- 2.2.6.post2 更新说明:[`docs/updates/2.2.6.post2.zh-CN.md`](docs/updates/2.2.6.post2.zh-CN.md)
- 2.2.6.post1 更新说明:[`docs/updates/2.2.6.post1.zh-CN.md`](docs/updates/2.2.6.post1.zh-CN.md)
- 2.2.6 更新说明:[`docs/updates/2.2.6.zh-CN.md`](docs/updates/2.2.6.zh-CN.md)
- 2.2.5 更新说明:[`docs/updates/2.2.5.zh-CN.md`](docs/updates/2.2.5.zh-CN.md)
Expand Down
4 changes: 2 additions & 2 deletions docs/skill/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ description: Build, assemble, inspect, reconstruct, and export parametric CAD mo
license: Apache-2.0
metadata:
project: simplecadapi
version: 2.2.6.post1
version: 2.2.6.post2
package-name: simplecadapi
package-version: 2.2.6.post1
package-version: 2.2.6.post2
---

# SimpleCAD SDK Skill
Expand Down
9 changes: 5 additions & 4 deletions docs/skill/references/docs/api/NotebookRun.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Class Definition

```python
class NotebookRun(config: NotebookConfig, product: Product, values: Mapping[str, Any], cells: tuple[CellReport, ...], dependencies: frozenset[Path])
class NotebookRun(config: NotebookConfig, product: Product | None, values: Mapping[str, Any], cells: tuple[CellReport, ...], dependencies: frozenset[Path])
```

*Source: runtime/runner.py*
Expand All @@ -17,6 +17,7 @@ class NotebookRun(config: NotebookConfig, product: Product, values: Mapping[str,
The outcome of :func:`run_notebook`.

``product`` is the notebook's product and ``definition`` its durable
definition; ``values`` holds every top-level variable, ``cells`` one
report per cell in notebook order, and ``dependencies`` the files
outside the cells the run depends on.
definition (``None`` for a partial run — see ``through``/``product``);
``values`` holds every top-level variable, ``cells`` one report per cell
in notebook order, and ``dependencies`` the files outside the cells the
run depends on.
8 changes: 8 additions & 0 deletions docs/skill/references/docs/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,12 @@ This index includes generated docs for the public SimpleCAD API surface, includi
## 3D Operations

- [extrude_rsolid](extrude_rsolid.md) *(from operators/features.py)* `top-level`
- [extrude_taper_rsolid](extrude_taper_rsolid.md) *(from operators/features.py)* `top-level`
- [extrude_until_rsolid](extrude_until_rsolid.md) *(from operators/features.py)* `top-level`
- [loft_rshell](loft_rshell.md) *(from operators/geometry.py)* `top-level`
- [loft_rsolid](loft_rsolid.md) *(from operators/features.py)* `top-level`
- [revolve_rsolid](revolve_rsolid.md) *(from operators/features.py)* `top-level`
- [sweep_multisection_rsolid](sweep_multisection_rsolid.md) *(from operators/features.py)* `top-level`
- [sweep_rsolid](sweep_rsolid.md) *(from operators/features.py)* `top-level`

## Tagging and Selection
Expand Down Expand Up @@ -345,6 +348,7 @@ This index includes generated docs for the public SimpleCAD API surface, includi
- [add_revolute_constraint_rassembly](add_revolute_constraint_rassembly.md) *(from operators/product.py)* `top-level`
- [and_](and_.md) *(from ql.py)* `submodule:ql`
- [assign_material_rpart](assign_material_rpart.md) *(from operators/product.py)* `top-level`
- [boolean_rsolidlist](boolean_rsolidlist.md) *(from operators/boolean.py)* `top-level`
- [canonical_frame](canonical_frame.md) *(from product/placement.py)* `submodule:product/placement`
- [capture](capture.md) *(from product/capture.py)* `top-level`
- [constrain_angle_rsketch](constrain_angle_rsketch.md) *(from operators/sketch.py)* `top-level`
Expand Down Expand Up @@ -377,6 +381,7 @@ This index includes generated docs for the public SimpleCAD API surface, includi
- [constrain_symmetric_rsketch](constrain_symmetric_rsketch.md) *(from operators/sketch.py)* `top-level`
- [constrain_tangent_rsketch](constrain_tangent_rsketch.md) *(from operators/sketch.py)* `top-level`
- [constrain_vertical_rsketch](constrain_vertical_rsketch.md) *(from operators/sketch.py)* `top-level`
- [draft_rsolid](draft_rsolid.md) *(from operators/features.py)* `top-level`
- [explain_tag](explain_tag.md) *(from operators/selection.py)* `top-level`
- [fill_holes_rshell](fill_holes_rshell.md) *(from operators/geometry.py)* `top-level`
- [fit_point_grid_rface](fit_point_grid_rface.md) *(from operators/geometry.py)* `top-level`
Expand All @@ -394,6 +399,7 @@ This index includes generated docs for the public SimpleCAD API surface, includi
- [measure_constraint_residual_rconstraintresidual](measure_constraint_residual_rconstraintresidual.md) *(from operators/product.py)* `top-level`
- [meta](meta.md) *(from ql.py)* `submodule:ql`
- [not_](not_.md) *(from ql.py)* `submodule:ql`
- [offset_rsolid](offset_rsolid.md) *(from operators/features.py)* `top-level`
- [operation_event](operation_event.md) *(from ql.py)* `submodule:ql`
- [or_](or_.md) *(from ql.py)* `submodule:ql`
- [origin_role](origin_role.md) *(from ql.py)* `submodule:ql`
Expand All @@ -404,6 +410,7 @@ This index includes generated docs for the public SimpleCAD API surface, includi
- [placement_ticks](placement_ticks.md) *(from product/placement.py)* `submodule:product/placement`
- [radial_pattern_rsolidlist](radial_pattern_rsolidlist.md) *(from operators/transform.py)* `top-level`
- [render_screenshot_rpath](render_screenshot_rpath.md) *(from operators/features.py)* `top-level`
- [scale_rsolid](scale_rsolid.md) *(from operators/transform.py)* `top-level`
- [select](select.md) *(from ql.py)* `submodule:ql`
- [set_public_connector_rassembly](set_public_connector_rassembly.md) *(from operators/product.py)* `top-level`
- [sew_faces_rshell](sew_faces_rshell.md) *(from operators/geometry.py)* `top-level`
Expand All @@ -412,6 +419,7 @@ This index includes generated docs for the public SimpleCAD API surface, includi
- [source_binding](source_binding.md) *(from ql.py)* `submodule:ql`
- [source_topology](source_topology.md) *(from ql.py)* `submodule:ql`
- [tag](tag.md) *(from ql.py)* `submodule:ql`
- [transform_rsolid](transform_rsolid.md) *(from operators/transform.py)* `top-level`
- [trim_surface_rface](trim_surface_rface.md) *(from operators/geometry.py)* `top-level`
- [twisted_sweep_rsolid](twisted_sweep_rsolid.md) *(from operators/features.py)* `top-level`
- [unground_component_rassembly](unground_component_rassembly.md) *(from operators/product.py)* `top-level`
Expand Down
4 changes: 3 additions & 1 deletion docs/skill/references/docs/api/add_bspline_rsketch.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ def add_bspline_rsketch(sketch: Sketch, entity_id: str, start: Union[SketchRef,
Add a B-spline curve entity to a sketch.

The start/end point refs link the B-spline into a closed profile
loop. Control points may be literal 2-D coordinates or point refs.
loop. A closed curve may reuse one seam ref for both endpoints.
Control points may be literal 2-D coordinates or point refs. A periodic
seam links topology without replacing the periodic curve's poles.
45 changes: 45 additions & 0 deletions docs/skill/references/docs/api/boolean_rsolidlist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# boolean_rsolidlist

## API Definition

```python
def boolean_rsolidlist(left: Sequence[Solid], right: Sequence[Solid], operation: str) -> list[Solid]
```

*Source: operators/boolean.py*

## Import Surface

- top-level: `from simplecadapi import boolean_rsolidlist`

## Description

Apply a set boolean to two body groups, retaining every result solid.

Members of each group are a geometric set. Unlike single-solid booleans,
a cut or intersection may return several solids or an empty list.
Topology lineage is partial; the ordered inputs and all output slots are
recorded so downstream features can replay the same geometry.

## Parameters

### left

- **Description**: The first group of solids.

### right

- **Description**: The second group of solids.

### operation

- **Description**: ``"cut"``, ``"intersect"`` or ``"union"``.

## Returns

The result solids, possibly several or none.

## Raises

- **TypeError**: A group contains something that is not a Solid.
- **ValueError**: ``operation`` is unknown, or a member is invalid or empty.
78 changes: 54 additions & 24 deletions docs/skill/references/docs/api/draft_rsolid.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,69 @@
# draft_rsolid

## API Definition

```python
def draft_rsolid(
solid: Solid,
faces_to_draft: Sequence[Face] | ShapeSelector,
angle: ScalarLike,
plane_origin: Sequence[float] = (0, 0, 0),
plane_normal: Sequence[float] = (0, 0, 1),
) -> Solid
def draft_rsolid(solid: Solid, faces_to_draft: Sequence[Face] | ShapeSelector, angle: ScalarLike, plane_origin: Sequence[float] = (0, 0, 0), plane_normal: Sequence[float] = (0, 0, 1)) -> Solid
```

*Source: operators/draft.py*
*Source: operators/features.py*

## Import Surface

- top-level: `from simplecadapi import draft_rsolid`

## Description

Draft planar, cylindrical or conical faces by a signed angle in degrees.

The neutral plane fixes the unchanged section: the selected faces lean
toward or away from it. Its origin and normal are in current
coordinate-system coordinates. Face selection is checked against the input
body and retained as graph inputs for strict replay. The input solid is
preserved, the output must be one valid solid, and a zero angle records an
unchanged result. Other surface families are explicitly rejected.

The operation is recorded as ``make_draft_rsolid``; the body and selected
faces are ordered inputs, and the angle, neutral plane and face selection
nodes are parameters, so model JSON replay is strict.

## Parameters

### solid

- **Description**: The body to draft.

### faces_to_draft

- **Description**: Faces of ``solid``, or a QL selector that picks them.

Import with `from simplecadapi import draft_rsolid`.
### angle

Apply a signed draft angle in degrees to selected planar, cylindrical, or
conical faces. The neutral plane retains its original section while the selected
faces lean toward or away from it. Its origin and normal use the current
coordinate system. The input solid is preserved, and the output must be one
valid solid. A zero angle records an unchanged result.
- **Description**: Draft angle in degrees, strictly between -90 and 90.

### plane_origin

- **Description**: A point of the neutral plane.

### plane_normal

- **Description**: Normal of the neutral plane; must be nonzero.

## Returns

The drafted solid.

## Raises

- **TypeError**: ``solid`` is not a Solid.
- **ValueError**: Empty selection, a selection that is not made of faces of ``solid``, an unsupported surface family, a zero plane normal, or a nonfinite or out-of-range angle.

## Examples

```python
import simplecadapi as scad
from simplecadapi import ql

body = scad.make_box_rsolid(10, 10, 10)
right = ql.faces().where(ql.prop("geom.normal.x", ">", 0.9)).exactly(1)
drafted = scad.draft_rsolid(body, right, angle=10)
```

Selections may be explicit faces from the body or a QL selector. Empty
selections, faces from another body, unsupported surface families, a zero plane
normal, and nonfinite parameters are rejected. The angle must be strictly
between -90 and 90 degrees. Kernel failures and invalid topology raise errors.

The operation `make_draft_rsolid` records the body and selected faces as ordered
inputs. Parameters preserve the angle, neutral plane, and face selection nodes
for strict model JSON replay.
Loading
Loading