Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
135 commits
Select commit Hold shift + click to select a range
a8a84c6
editor: GUI-made features, a typed operation registry and the command…
NiJingzhe Nov 2, 2026
3171a01
editor: a blank notebook, the product cell with the first GUI feature…
NiJingzhe Nov 2, 2026
ff6c8a5
editor-web: a feature tree, a command bar and spec-generated paramete…
NiJingzhe Nov 2, 2026
1381ac8
editor: sketches with constraints as GUI features, and a solve endpoi…
NiJingzhe Nov 2, 2026
04dbb60
editor: assemblies as a GUI feature, with the connectors a part declares
NiJingzhe Nov 2, 2026
ad1e783
editor-web: a constrained sketch canvas
NiJingzhe Nov 2, 2026
a0fc3ea
editor: connectors of a GUI part, written into its product cell
NiJingzhe Nov 2, 2026
b1f6460
editor: a sketch can lie on any plane frame, and extrudes along its n…
NiJingzhe Nov 2, 2026
08d580e
sketch: trim_rsketch, extend_rsketch and diff_sketch_rsketchdiff as S…
NiJingzhe Nov 2, 2026
8069026
editor: sketch in the 3D viewport on a datum plane or a picked face; …
NiJingzhe Nov 2, 2026
b74eda7
editor-web: trim and extend tools, an assembly panel and part connectors
NiJingzhe Nov 2, 2026
a4ddd70
SDK: fillet_corner_rsketch, chamfer_corner_rsketch, project_rsketch a…
NiJingzhe Nov 2, 2026
f2aa06e
editor: the new SDK operations through the sketch document and the as…
NiJingzhe Nov 2, 2026
6ea7c02
editor-web: fillet and chamfer corner, project, an exploded view, and…
NiJingzhe Nov 2, 2026
c0908d2
editor: name clashes are a message, and a cell reported late is found…
NiJingzhe Nov 2, 2026
87ba477
editor-web: connector frames as real 3D objects, on shared scene-laye…
NiJingzhe Nov 3, 2026
f8c0a96
editor-web: sketches stay visible, pick a sketch to extrude, a contex…
NiJingzhe Nov 3, 2026
b19b54f
editor: a new solid says at once how it meets the body (join, cut, in…
NiJingzhe Nov 3, 2026
a7af887
editor-web: an operation chooser (join, cut, intersect) when a new so…
NiJingzhe Nov 3, 2026
fccd75e
sketch: one source of truth for profiles (inspect_sketch_rsketchprofi…
NiJingzhe Nov 3, 2026
b3a0fc8
editor-web: the sketch canvas looks through an orthographic projection
NiJingzhe Nov 3, 2026
f0dd9de
editor-web: the viewport and the sketch overlays clip their overflow
NiJingzhe Nov 3, 2026
d683a63
editor-web: narrower left panel, tabs stay put on horizontal scroll, …
NiJingzhe Nov 3, 2026
40dc5ee
editor-web: two lines now also offer coincident (join end to end)
NiJingzhe Nov 3, 2026
60fa2a8
editor: a hole drills along an axis, the picked face's normal or a fr…
NiJingzhe Nov 3, 2026
f6a44f3
editor-web: manual mode and code mode, one switch in the top bar, sid…
NiJingzhe Nov 3, 2026
39ddeba
docs: topological naming research (FreeCAD ElementMap, Onshape queries)
NiJingzhe Nov 3, 2026
16b845f
editor: pull or push a picked flat face along its normal (extrude_fac…
NiJingzhe Nov 3, 2026
ff28293
editor-web: type the next point while drawing (x/y, length and angle,…
NiJingzhe Nov 3, 2026
073879f
runtime: a kind = "part" notebook needs no product cell; its one open…
NiJingzhe Nov 3, 2026
d39e2bd
editor-web: the product badge says when the part is implicit
NiJingzhe Nov 3, 2026
da66680
feat(refs): resolve element references through recorded topology hist…
NiJingzhe Nov 3, 2026
86d2257
docs: stable references design, audit and staged plan; SDK defects 21-25
NiJingzhe Nov 3, 2026
a607d39
sketch: where curves cross is the SDK's answer (inspect_sketch_rsketc…
NiJingzhe Nov 3, 2026
b607c85
feat(product): multi-body parts: a Part holds one Solid or several na…
NiJingzhe Nov 3, 2026
7a59047
docs: multi-body part design (data model, API, editor UX, plan) and S…
NiJingzhe Nov 3, 2026
172120e
skill: a kind = "part" notebook needs no product cell (the runtime ma…
NiJingzhe Nov 3, 2026
0355869
feat(refs): history through transform/scale/offset/draft, stable anch…
NiJingzhe Nov 3, 2026
99d34d9
catalog: the meaning of a parameter is its type in the binding (Lengt…
NiJingzhe Nov 3, 2026
c6149f4
style: keep the NOLINT on the conversion line
NiJingzhe Nov 3, 2026
2b3d590
editor: every SDK operation the forms can offer is a feature made fro…
NiJingzhe Nov 3, 2026
df38241
fix(tracking): an input that stays in the result is preserved even wh…
NiJingzhe Nov 3, 2026
e33f50e
editor-web: forms for value slots (named values of the kinds an opera…
NiJingzhe Nov 3, 2026
9778a8e
feat(product): owner decisions on multi-body parts
NiJingzhe Nov 3, 2026
38d6e90
sca ops: the operation catalog on the command line; skill: how to fin…
NiJingzhe Nov 3, 2026
4744e73
catalog: surface and sketch operations say what each parameter means …
NiJingzhe Nov 3, 2026
6e61c38
docs: what the SDK can and cannot do for interactive NURBS editing; d…
NiJingzhe Nov 3, 2026
56d2a54
Merge branch 'wip/types-surface-sketch' into feat/gui-modeling
NiJingzhe Nov 3, 2026
cbebe6f
catalog: product, assembly and std operations say what every paramete…
NiJingzhe Nov 3, 2026
2ca4b7b
editor: a direction is plain numbers in the params cell, not millimet…
NiJingzhe Nov 3, 2026
9d172af
merge wip/types-product-std: typed product, assembly and standard-lib…
NiJingzhe Nov 3, 2026
c41d366
catalog: a union of spellings of one value has that value's kind (Seq…
NiJingzhe Nov 3, 2026
7556a4a
bindings: geometry and feature operations say what each parameter mea…
NiJingzhe Nov 3, 2026
76fcb1a
editor: a grid of points (a control net) is a form slot; catalog read…
NiJingzhe Nov 3, 2026
56d887b
merge wip/types-geometry: typed geometry and feature signatures; one …
NiJingzhe Nov 3, 2026
8ffc8c0
bindings: one vocabulary for signature types (Renamed<T, Tag>, AnyOf<…
NiJingzhe Nov 3, 2026
facccaa
feat(tags): tags are a view over the recorded history
NiJingzhe Nov 3, 2026
45d441c
feat(refs): persistence across the cell cache, bodies, naming version…
NiJingzhe Nov 3, 2026
37e6dd8
merge research/multi-solid: a Part holds one Solid or several named b…
NiJingzhe Nov 3, 2026
814871b
merge research/stable-geometry-refs: references and tags resolve thro…
NiJingzhe Nov 3, 2026
900f7f8
editor-web: the header counts parts and the bodies of a multi-body part
NiJingzhe Nov 3, 2026
2c15b2e
editor: the page is served no-cache so a rebuilt UI loads on the next…
NiJingzhe Nov 3, 2026
526aa07
editor-web: a connector's frame can be set by hand (origin, a move al…
NiJingzhe Nov 3, 2026
c8722c3
fix(tags): a restored value counts a history-derived tag witness once
NiJingzhe Nov 4, 2026
cd383f0
Merge branch 'fix/tag-view-cache' into feat/gui-modeling
NiJingzhe Nov 4, 2026
c2a456c
surface: recorded edits of existing curves and surfaces (C++ kernel a…
NiJingzhe Nov 4, 2026
4ff6617
feat(product): set_body_appearance_rpart: a display colour, opacity a…
NiJingzhe Nov 4, 2026
9df1d77
sdk: curve/surface edit operations exported, recorded and replayed fr…
NiJingzhe Nov 4, 2026
c18d6b9
editor: a colour slot for display colours; naming a face is the tag o…
NiJingzhe Nov 4, 2026
f021b33
surface edits: sub-entity tags follow without a session; stubs, API p…
NiJingzhe Nov 4, 2026
a0879d7
docs: API pages and stubs for set_body_appearance_rpart; Body colour/…
NiJingzhe Nov 4, 2026
e35c573
editor-web: a colour input for colour slots; the viewer draws each bo…
NiJingzhe Nov 4, 2026
ae8aeaa
skill: colours and names for people (set_body_appearance_rpart; a fac…
NiJingzhe Nov 4, 2026
506d980
surface edits: inspect reports a side a converter turned into a 2D B-…
NiJingzhe Nov 4, 2026
9a84b1d
Merge branch 'feat/nurbs-edit-ops' into feat/gui-modeling
NiJingzhe Nov 4, 2026
3d62a95
merge feat/body-appearance: body colour, opacity and display name (se…
NiJingzhe Nov 4, 2026
4900aea
test: untrack seven pre-port test files committed by mistake
NiJingzhe Nov 4, 2026
26c1729
editor-web: the model shows in the sketch view (faces and edges)
NiJingzhe Nov 4, 2026
f4cb667
sketch: B-splines in the sketch editor (spline tool B: click control …
NiJingzhe Nov 4, 2026
a4b7150
sketch: trim / extend / crossings cut B-splines (and are cut by B-spl…
NiJingzhe Nov 4, 2026
be771ed
sketch: an extended Bezier chain stays one; the editor document keeps…
NiJingzhe Nov 4, 2026
81b1f65
test: B-spline trim / extend / crossings (pytest), replay and the edi…
NiJingzhe Nov 4, 2026
a47c92a
docs: trim / extend / crossings / point_on docstrings and API pages f…
NiJingzhe Nov 4, 2026
c6f01eb
sdk: workplanes are recorded values (make_workplane_*_rworkplane); sk…
NiJingzhe Nov 4, 2026
b9143ec
docs: API pages and stubs for the workplane constructors; SimpleWorkp…
NiJingzhe Nov 4, 2026
dc6aabd
ref: scad.ref (stable references as code) and ql.ref (a reference as …
NiJingzhe Nov 4, 2026
271c7ce
sketch: a periodic B-spline's crossings are wrapped into one period b…
NiJingzhe Nov 4, 2026
d137ec5
docs: API pages for scad.ref (ref.<name>), ql.ref, ElementRef and Ele…
NiJingzhe Nov 4, 2026
c0f29be
editor: a workplane feature from picked geometry; a sketch plane can …
NiJingzhe Nov 4, 2026
44e9f85
editor-web: Space makes a workplane from the selection; workplanes dr…
NiJingzhe Nov 4, 2026
cbdc8a2
editor-web: test which selections offer the workplane command
NiJingzhe Nov 4, 2026
e13a552
runtime/editor: a cell that only makes workplanes leaves the body it …
NiJingzhe Nov 4, 2026
3bf28ad
editor: selections are scad.ref statements; the server names picks in…
NiJingzhe Nov 4, 2026
6c3dc5e
editor: a feature row lists the workplane it reads
NiJingzhe Nov 4, 2026
a3baee9
skill: workplanes as recorded values (simple_workplane, datums, sketc…
NiJingzhe Nov 4, 2026
8a92c22
editor-web: a failing feature shows its references (green / amber / r…
NiJingzhe Nov 4, 2026
dcc7926
skill: scad.ref where a particular entity is meant, ql where a rule i…
NiJingzhe Nov 4, 2026
c08a4ea
editor-web: a spline draft can be finished without the keyboard (clic…
NiJingzhe Nov 4, 2026
a90fb3b
merge feat/workplanes: workplanes are values with recorded constructo…
NiJingzhe Nov 4, 2026
0399b49
merge feat/public-refs: scad.ref (readable, parseable stable referenc…
NiJingzhe Nov 4, 2026
c3368e6
fillet and chamfer take the pieces of a split body; bigger snap circl…
NiJingzhe Nov 4, 2026
cc2ee95
the pieces of a split body flow on: one-shape operations apply to eve…
NiJingzhe Nov 4, 2026
98e24b6
tags follow their entity as references do: a split names the pieces <…
NiJingzhe Nov 4, 2026
7d37131
make_workplane_offset_rworkplane: a workplane moved and turned relati…
NiJingzhe Nov 4, 2026
fabbbe2
editor interaction: workplanes placed with move/turn handles (make_wo…
NiJingzhe Nov 4, 2026
a69d1ef
3D curves drawn in the viewport (W: lines, arcs, splines on workplane…
NiJingzhe Nov 4, 2026
3701e43
editor: connectors placed on a face with move/turn handles (the same …
NiJingzhe Nov 4, 2026
84974c7
editor: the viewport renders with three's WebGPURenderer (WebGL 2 whe…
NiJingzhe Nov 5, 2026
6e745f3
editor: opening another notebook drops what the last one showed (work…
NiJingzhe Nov 5, 2026
3bacb93
editor viewport: level of detail (a part seen up close is tessellated…
NiJingzhe Nov 5, 2026
d35c92e
a new part notebook is empty (sca new and the editor's new; the param…
NiJingzhe Nov 5, 2026
37a3fe9
editor manual mode: the viewport takes the whole window, the panels f…
NiJingzhe Nov 5, 2026
8e48abd
editor i18n: English and Chinese (i18next; the English text is the ke…
NiJingzhe Nov 5, 2026
c7c3c3c
editor: an operation in progress (lib/operation-session.ts) instead o…
NiJingzhe Nov 5, 2026
8e01e19
inset_face_rsolid: a planar face's loops moved inside it are imprinte…
NiJingzhe Nov 5, 2026
69ac640
press_pull_rsolid: one signed distance pulls a planar face out (its p…
NiJingzhe Nov 5, 2026
a68f5d5
editor: one layout for both modes: the left column holds the panels (…
NiJingzhe Nov 5, 2026
0e90fc1
editor: the left column slides like the mode switch (both modes' pane…
NiJingzhe Nov 5, 2026
5aca0dc
editor: the viewport's ground and view controls, smooth folds and the…
NiJingzhe Nov 5, 2026
d3eb5a6
editor i18n: sketch mode in Chinese: the toolbar (tools, toggles, con…
NiJingzhe Nov 5, 2026
5c2acac
runtime: a notebook with no Part, Assembly or solid yet is no fault: …
NiJingzhe Nov 5, 2026
1505ff1
editor: shell as an operation in progress: picked faces, Shell, and t…
NiJingzhe Nov 5, 2026
3e6ea0b
editor: 3D curves are picked with the sketches (the "sketch / curve" …
NiJingzhe Nov 5, 2026
53de920
editor: a 3D curve is one edge: a path drawn in one go becomes one cu…
NiJingzhe Nov 5, 2026
f8a13de
sdk: an edge is taken wherever a wire is (a sweep path, a loft sectio…
NiJingzhe Nov 5, 2026
6f1c248
editor: several curves picked join into a wire (the `wire` feature: m…
NiJingzhe Nov 5, 2026
6813528
sdk: sew_faces_rshell takes faces and shells (a shell is sewn as its …
NiJingzhe Nov 6, 2026
08050b1
editor: surfaces from curves and a solid from surfaces
NiJingzhe Nov 6, 2026
80fb891
editor i18n: the assembly panel (connectors, components, constraints,…
NiJingzhe Nov 6, 2026
f3c4d16
editor: the 3D curve drawer starts with a free name (path, path_2 ...…
NiJingzhe Nov 6, 2026
2ee7114
editor: code mode only for the release: manual modelling is switched …
NiJingzhe Nov 8, 2026
4eedc7e
cpp: sketch/edit.cpp returns an explicit CurveHandle (GCC does not co…
NiJingzhe Nov 8, 2026
41ae6d5
test: untrack the seven pre-port test files again (swept back in by 6…
NiJingzhe Nov 8, 2026
8d8532c
tests: goldens follow the edge-as-wire change (f8a13de): an edge give…
NiJingzhe Nov 8, 2026
3ad47b6
README: the idea, the evidence, the skill, the plugins
NiJingzhe Nov 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@ user-facing notes live in [`docs/updates/`](docs/updates/) (English and

## Unreleased

### Added
- Editing existing curves and surfaces as recorded operations (the SDK half of NURBS control-point editing):
`inspect_curve_rcurvedata` / `inspect_surface_rsurfacedata` read degree, poles, weights, knots and trimming;
`set_*_poles`, `move_*_poles`, `set_*_weights`, `insert_*_knot`, `elevate_*_degree` (curves `_redge`, surfaces
`_rface`), `convert_to_bspline_redge/rface` (the explicit step for lines, circles, planes, cylinders) and
`rebuild_curve_redge/rface` return a new shape, record a topology delta (tags and references follow the face and
its edges) and replay from model JSON. A trimmed face keeps its trimming. `sample_curve_rcurvature` and
`sample_surface_risocurves` give an editor a curvature comb and clipped isocurves.

### Changed
- The editor offers its code mode only. Manual modelling (features, sketches, assemblies by buttons and dialogs) is built
but switched off (`editor-web/src/lib/manual-mode.ts`) until it has a plan of its own: no mode switch, command bar or
manual keys (`/`, `W`, Space, Ctrl+Z on features, `6`). The viewport keeps what was made for it: three's WebGPURenderer
(WebGL 2 as the fallback), level of detail (a part seen up close is tessellated again by the kernel from the in-memory
BREP, `POST /api/preview/refine`), instanced parts, BVH picking, and smooth shading from exact surface normals.

### Fixed
- A stable reference into a face or shell body (no solid) resolves; it raised `cannot resolve QL selector scope`.

## 2.2.7 — 2026-10-30

### Fixed
Expand Down
801 changes: 90 additions & 711 deletions README.md

Large diffs are not rendered by default.

682 changes: 90 additions & 592 deletions README.zh-CN.md

Large diffs are not rendered by default.

391 changes: 391 additions & 0 deletions design-docs/multi-solid-design.md

Large diffs are not rendered by default.

99 changes: 99 additions & 0 deletions design-docs/nurbs-editing-capability.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# NURBS editing in a GUI: what the SDK can and cannot do today

Status: research, 2026-11-04, branch `wip/types-surface-sketch` (cut from `feat/gui-modeling`). Nothing here is
implemented; the last section lists the C++ operations a Plasticity-level editor would need.

## Two ways into OpenCASCADE from Python

- **Public SDK operations** (`*_r<kind>` in `simplecadapi`, `simplecadapi.surface`). They are recorded in the graph,
replay, carry tags and appear in `simplecadapi.catalog`. A GUI or agent can only rely on these.
- **The private OCP-compat layer** `simplecadapi._cpp.occt.*` (`src/cpp/bindings/python/occt/bind_occt_{core,query,algo}.cpp`),
reached from a shape through `Shape.wrapped` (`bind_topo.cpp`, `bind_common`). It mirrors part of OCP for the internal
Python layers (inspect, translators). It is not recorded, not replayable and not documented. Edits made through it are
invisible to the graph and have no way back into topology.

Legend: **public** = a recorded SDK op; **private** = only through `_cpp.occt`; **internal** = used inside the C++ kernel, not
exposed; **absent** = not linked anywhere.

## Capability by capability

| Capability | Status | Evidence |
|---|---|---|
| Read poles / weights / knots / multiplicities / degree of an existing Edge | public (read-only) | `inspect_shape_rbrepinspection` (`src/simplecadapi/inspect/brep/inspect.py`, `_edge_parameters`); native `_bspline_curve_of(edge)` (`bind_sdk_compat.cpp`, `bspline_curve_dict`) |
| Same for a Face | public (read-only) | `inspect.py` `_surface_parameters` (poles, weights, knots, mults of a B-spline surface) |
| Read through OCCT objects | private | `Geom_BSplineCurve` / `Geom_BSplineSurface` / Bezier bound in `bind_occt_query.cpp` (Poles, Weights, Knots, Multiplicities, Degree, UDegree/VDegree); `BRep_Tool.Curve_s/Surface_s/CurveOnSurface_s` in `bind_occt_core.cpp` |
| Write a pole / weight / knot of an existing curve | private only | `bind_occt_query.cpp`: `Geom_BSplineCurve.SetPole/SetWeight/SetKnot(s)/IncreaseMultiplicity`, Bezier `SetPole/SetWeight` |
| Write a pole / weight of an existing surface | private only | `Geom_BSplineSurface.SetPole/SetWeight`, `Geom_BezierSurface.SetPole/SetWeight` (`bind_occt_query.cpp`) |
| Rebuild an Edge/Face after such an edit | absent | no op rebuilds topology from a modified `Geom_*`; the modified handle is shared with the original shape (mutation in place, unrecorded) |
| Degree elevation | private only | `Geom_BSplineCurve.IncreaseDegree`, `Geom_BSplineSurface.IncreaseDegree` (`bind_occt_query.cpp`) |
| Knot insertion / removal | private, curves only | `Geom_BSplineCurve.InsertKnot/RemoveKnot` (`bind_occt_query.cpp`); no `InsertUKnot/RemoveUKnot` for surfaces |
| Fit a surface through a point grid | public | `fit_point_grid_rface` (`src/cpp/src/surface/fitter.cpp`, `GeomAPI_PointsToBSplineSurface`, smoothing weights) |
| Interpolate a curve through points | public | `make_interpolated_spline_redge/rwire`, `make_periodic_spline_rwire` (`src/cpp/src/kernel/curves.cpp`, `GeomAPI_Interpolate`) |
| Approximate a curve (least squares, tolerance) | absent | `GeomAPI_PointsToBSpline` is not linked |
| Refit / simplify an existing curve or face, convert to NURBS | private / absent | `GeomConvert.CurveToBSplineCurve_s/SurfaceToBSplineSurface_s` private (`bind_occt_query.cpp`); `BRepBuilderAPI_NurbsConvert`, `ShapeCustom`, `BSplineRestriction`, `Approx_*` absent |
| G0/G1/G2 boundary conditions when filling | public | `make_surface_patch_rface`, `fill_holes_rshell` with `SurfaceBoundary(edge, continuity="C0"/"G1"/"G2", support=face)` -> `BRepOffsetAPI_MakeFilling` (`fitter.cpp`, `order_of`) |
| Continuity analysis between two faces (G0/G1/G2 deviation along an edge) | absent (one internal probe) | `LocalAnalysis`, `GeomLProp` not linked; dihedral angle along an edge is internal (`src/cpp/src/ops/features/probes.cpp`) |
| Gordon / ruled / loft / Bezier surfaces | public | `make_gordon_surface_rface` (`gordon.cpp`), `make_ruled_surface_rface`, `loft_rshell` / `loft_rsolid`, `make_bezier_surface_rface` (`faces_from_data.cpp`), sweeps (`sweep_rsolid`, `sweep_multisection_rsolid`, ...) |
| Blend surface between two faces (free, not a solid edge) | absent | only `fillet_rsolid` / `chamfer_rsolid` on solid edges (`BRepFilletAPI_*`, `semantic/tracking_blends.cpp`); no `GeomFill_*` / `BRepBlend` |
| Offset a surface | absent | `offset_rsolid` / `shell_rsolid` are solid-only (`ops/features/offsets.cpp`, `MakeThickSolid`); no `Geom_OffsetSurface`, no face offset |
| Extend a surface | absent | no `GeomLib::ExtendSurfByLength`, no `ShapeExtend` |
| Trim a surface by curves | public | `trim_surface_rface(carrier, outer, holes)` (`src/cpp/src/surface/trim.cpp`: projects the wire, checks pcurves with `GeomLib_CheckCurveOnSurface`, `BRepAlgoAPI_Common`) |
| Split a face by a curve | absent (internal splitter) | `BRepAlgoAPI_Splitter` only inside `extrude_until`; no `BRepFeat_SplitShape` |
| Untrim / read the trimming loops in UV | internal | pcurves read in `trim.cpp` via `BRep_Tool::CurveOnSurface`; no op returns them |
| Curve on surface (edge from a 2D curve on a face) | absent | `BRepBuilderAPI_MakeEdge(Geom2d_Curve, Surface)` not bound/used (MakeEdge takes 3D curves only, `bind_occt_algo.cpp`) |
| Project a point onto a surface | internal / private | `GeomAPI_ProjectPointOnSurf` in `trim.cpp`, `ShapeAnalysis_Surface` in `probes.cpp`; private binding in `bind_occt_query.cpp` |
| Project a curve onto a surface | absent | `BRepProj_Projection` not linked; `project_rsketch` only projects onto a sketch plane (`src/cpp/src/sketch/project.cpp`) |
| Isocurves (U/V iso lines) | private | `Geom_Surface.UIso/VIso` (`bind_occt_query.cpp`); used inside the guided-loft recipe (`bind_sdk_compat.cpp`); no op |
| Evaluate a curve / surface (point, derivatives, curvature) | private (sampling public) | `Edge.sample(count)` public (`bind_ops_geometry.cpp`); `D0..DN`, `BRepLProp_SLProps` curvatures private; no curve curvature (`CLProps`), no curvature comb |
| Sketch B-splines with poles / knots / weights | public | `add_bspline_rsketch(..., control_points, degree, knots, multiplicities, weights, periodic)` (`bind_sketch.cpp`); 3D `make_spline_redge/rwire` (`bind_ops_geometry.cpp`) |
| Editor hooks for control-point editing | absent | `src/simplecadapi/editor` only maps `bspline_curve/surface` to the BSPLINE selection filter (`editor/selection.py`) |

OCCT classes already linked: Geom_BSplineCurve/Surface, Geom_Bezier*, GeomAPI_Interpolate, GeomAPI_PointsToBSplineSurface,
BRepOffsetAPI_MakeFilling, ThruSections, MakePipeShell, MakeThickSolid, MakeOffset (wires), BRepFill, BRepFilletAPI,
GeomConvert, GeomAPI_ProjectPointOnSurf, ShapeAnalysis_Surface/FreeBounds, GeomLib_CheckCurveOnSurface, BRepAlgoAPI_Common/Splitter,
BRepLProp_SLProps, Geom2d_*, BRepExtrema.

Not linked: GeomPlate, GeomFill, LocalAnalysis, GeomLProp, Geom_OffsetSurface, GeomLib::ExtendSurfByLength, ShapeExtend,
ShapeCustom, BRepBuilderAPI_NurbsConvert, BRepFeat_SplitShape, BRepProj_Projection, GeomAPI_PointsToBSpline, Approx_*.

## What this means for a GUI

The SDK can *build* every common freeform surface from data a GUI collects (control nets, curve networks, boundary
patches with G1/G2 supports, trims), and it can *read* the NURBS data of a result. It cannot *edit* an existing curve
or surface as a recorded operation: every edit a Plasticity-style control-point drag implies (move pole, set weight,
insert knot, elevate degree) exists only as unrecorded mutation through the private OCCT layer, and nothing rebuilds the
Edge/Face from the modified geometry. The editor must therefore keep the control net itself and re-run a constructor op
(`make_spline_redge`, `make_bezier_surface_rface`) on every drag, which loses the identity and tags of downstream topology
and has no answer for imported or derived (fillet, Gordon, filling) surfaces.

## Operations that would be needed (C++ kernel ops, recorded, catalog-typed)

Read:
1. `inspect_curve_rnurbs(edge)` / `inspect_surface_rnurbs(face)` - degree, poles (`Sequence[Point3]` / grid), weights,
knots, multiplicities, periodic/rational flags, parameter range; converts non-B-spline geometry on request
(`GeomConvert`). Today's data sits in `inspect_shape_rbrepinspection`; it needs to be a first-class typed value.
2. `evaluate_curve_rframe(edge, t)` / `evaluate_surface_rframe(face, u, v)` - point, derivatives, normal, curvatures
(`GeomLProp_CLProps/SLProps`), for curvature combs and zebra-like checks.
3. `measure_continuity_rcontinuity(face_a, face_b, edge, samples)` - G0 gap, G1 angle, G2 curvature deviation
(`LocalAnalysis_SurfaceContinuity`).

Edit (each returns a new Edge/Face, recorded, lineage preserved for tags):
4. `edit_curve_poles_redge(edge, poles=..., weights=...)` and `edit_surface_poles_rface(face, poles=..., weights=...)`
- replace some or all poles/weights, keep the trim (re-project the face's trim loops).
5. `insert_knot_redge` / `insert_knot_rface(face, u=|v=, multiplicity)`, `remove_knot_*` (tolerance-checked).
6. `elevate_degree_redge` / `elevate_degree_rface(face, u_degree, v_degree)`.
7. `rebuild_curve_redge(edge, degree, pole_count | tolerance)` / `rebuild_surface_rface(face, u_count, v_count, degree)`
(`GeomAPI_PointsToBSpline(Surface)`, `Approx_*`) and `convert_to_nurbs_rshape` (`BRepBuilderAPI_NurbsConvert`).

Build:
8. `blend_surface_rface(edge_a, face_a, edge_b, face_b, continuity="G1"|"G2")` (`GeomFill` / `GeomPlate`).
9. `offset_surface_rface(face, distance)` (`BRepOffsetAPI_MakeOffsetShape` on a face, `Geom_OffsetSurface`) and
`extend_surface_rface(face, edge, length, continuity)` (`GeomLib::ExtendSurfByLength`).
10. `split_face_rfacelist(face, tools)` (`BRepFeat_SplitShape` / `BRepAlgoAPI_Splitter`), `untrim_surface_rface(face)`.
11. `make_curve_on_surface_redge(face, uv_points | Geom2d spec)` and `project_curve_onto_face_redge(edge, face,
direction=None)` (`BRepProj_Projection`, `BRepAlgo_NormalProjection`).
12. `make_isocurve_redge(face, u=|v=)` (`UIso/VIso` + trim to the face).

Most important gaps, in order: (a) recorded edits of an existing curve/surface (4-6) - without them control-point
editing is a rebuild-from-scratch hack; (b) continuity measurement and blend surfaces (3, 8) - the core of class-A style
surfacing; (c) offset/extend/split of faces (9, 10) - routine surface workflow steps that have no op at all.
Loading
Loading