Fix the README's broken markdown and drop the unsourced speedup claim

Three fixes. The cadquery-ocp link was missing its closing bracket and rendered
literally. "As packages sit on our Gitea instance for, you must install" had a
stray word. And the headline "superlinear 7.0x speedup" cited nothing and is
contradicted by docs/design.md, which says binding call overhead was never the
bottleneck: the payoff is version velocity, footprint, ownership correctness and
the batch APIs upstream lacks. That is what the intro says now, and the one
measured number that does exist (face extraction 4.6-5.5x over the Python loop)
sits with the batch operations it belongs to.

Restructured onto the shared skeleton on the way through, adding a status, a
layout table and a links-out section.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WsxkJEmqEECM1PygXdN1zU
This commit is contained in:
2026-08-12 09:16:53 +02:00
co-authored by Claude Opus 5
parent 9f86845c25
commit b9fb8ca469
+52 -14
View File
@@ -1,26 +1,36 @@
# n3xd-ocp
Hand-written [nanobind](https://github.com/wjakob/nanobind) wrapper for the OpenCASCADE (OCCT) geometry kernel.
In comparison to [`cadquery-ocp](https://github.com/cadquery/OCP), we get superlinear 7.0x speedup on the use cases in `n3xd`.
Hand-written [nanobind](https://github.com/wjakob/nanobind) wrapper for the
OpenCASCADE (OCCT) geometry kernel. It installs as a top-level `OCP` and is a
drop-in replacement for [`cadquery-ocp`](https://github.com/cadquery/OCP): same
symbols, same call shapes. What it buys over upstream is version velocity (the
kernel is ours to bump), a much smaller footprint, correctness around object
ownership, and room to add APIs upstream does not offer, such as releasing the
GIL and extracting whole shapes in one call.
Start with [docs/design.md](docs/design.md) for the decisions,
[docs/building.md](docs/building.md) to build one, and
[docs/adding-symbols.md](docs/adding-symbols.md) to extend the surface.
## Status
The binding covers the subset of OCCT that `n3xd` actually uses, not the whole
kernel; run `tools/inventory.py` for the current count. Adding a class is a
routine, documented change, see
[docs/adding-symbols.md](docs/adding-symbols.md).
## Installation
As packages sit on our Gitea instance for, you must install by providing the specific url, like:
The packages sit on our Gitea instance, so install by pointing at its index:
```bash
uv pip install --index-url https://git.stroblme.de/api/packages/N3XD/pypi/simple/ \
--prerelease=allow n3xd-ocp
```
Versions are `<occt-version>.N`, enforced at configure time against the OCCT actually found.
Versions are `<occt-version>.N`, enforced at configure time against the OCCT
actually found.
## Usage
`OCP` mirrors [`cadquery-ocp`](https://github.com/cadquery/OCP) symbol-for-symbol, so code written against it runs unchanged:
`OCP` mirrors `cadquery-ocp` symbol-for-symbol, so code written against it runs
unchanged:
```python
from OCP.BRepPrimAPI import BRepPrimAPI_MakeBox
@@ -41,9 +51,16 @@ cut.Build()
result = cut.Shape()
```
One deliberate gap from upstream: constructors that run the algorithm immediately (the two-argument `BRepAlgoAPI_Cut(a, b)` form) aren't bound, only the deferred `SetArguments`/`SetTools`/`Build()` sequence above. See [docs/design.md](docs/design.md) for why.
One deliberate gap from upstream: constructors that run the algorithm
immediately (the two-argument `BRepAlgoAPI_Cut(a, b)` form) are not bound, only
the deferred `SetArguments`/`SetTools`/`Build()` sequence above. See
[docs/design.md](docs/design.md) for why.
`n3xd_ocp` adds a handful of batch operations OCP doesn't have. They run on the same OCCT build and take/return plain `OCP` shapes:
`n3xd_ocp` adds a handful of batch operations OCP does not have. They run on the
same OCCT build and take and return plain `OCP` shapes, and they exist because
doing the same work as a per-face Python loop is measurably slower (face
extraction came out 4.6-5.5x faster on ordinary geometry when the app adopted
it):
```python
import n3xd_ocp
@@ -55,7 +72,9 @@ data = n3xd_ocp.bintools.write_bytes(result) # BREP bytes, n
points, normals, uv_bounds = n3xd_ocp.sample.face_grid(face, 33) # a 33x33 UV grid on one face
```
`n3xd_ocp.helix` reaches OCCT 8.0's TKHelix, which upstream has no binding for. For N segments it wants N pitches, N turn counts and **N+1 diameters** — one per segment boundary, so consecutive values that differ taper across that segment:
`n3xd_ocp.helix` reaches OCCT 8.0's TKHelix, which upstream has no binding for.
For N segments it wants N pitches, N turn counts and **N+1 diameters**, one per
segment boundary, so consecutive values that differ taper across that segment:
```python
from OCP.gp import gp_Ax3, gp_Dir, gp_Pnt
@@ -69,11 +88,22 @@ builder.set_approx_parameters(1.0e-4)
builder.perform()
```
## Layout
| Path | What it is |
| --- | --- |
| `src/modules/` | The bound OCCT classes, one file per OCCT module |
| `src/ext/` | The `n3xd_ocp` extras: batch measure, tessellation, sampling, helix |
| `src/common/` | Handle and transient casters, the machinery every module relies on |
| `python/OCP/`, `python/n3xd_ocp/` | The Python packages and their type stubs |
| `occt/` | The Dockerfile that compiles OCCT 8.0.1 into the builder image |
| `tools/` | Inventory, signature diffing against upstream, and benchmarks |
## Build
Wheels are built on a dev box and published to the Gitea package registry [here](https://git.stroblme.de/api/packages/N3XD/pypi).
If you want to make modifications or build it yourself, here are some shortcuts:
Wheels are built on a dev box and published to the
[Gitea package registry](https://git.stroblme.de/api/packages/N3XD/pypi). To
build one yourself:
```bash
make image # compiles OCCT 8.0.1 into the builder image
@@ -81,3 +111,11 @@ make dev # incremental compile + tests
make wheel # compile, stubs, auditwheel, self-containment smoke test
make publish # publish to Gitea using .secret credentials
```
## More
- [docs/design.md](docs/design.md) — the decisions and the handle model
- [docs/building.md](docs/building.md) — the builder image and the wheel
- [docs/adding-symbols.md](docs/adding-symbols.md) — extending the surface
Licensed LGPL-2.1-only, following OCCT.