Skip to content

Releases: inventhq/PicoPie

picopie 0.7.0 — compiled active_values() traversal (~30× faster)

Choose a tag to compare

@Borderliner Borderliner released this 02 Jul 20:36
v0.7.0

Changed — active_values() is now compiled (~30× faster)

ScalarField.active_values() and VectorField.active_values() previously walked the sparse active-voxel set with a per-voxel Python callback — the same overhead class as the implicit-SDF path fixed in 0.6.0. They now use the compiled _fastloop extension: a native TraverseActive that writes straight into NumPy arrays via two nogil passes (count, then fill an exactly-sized buffer).

  • ~30× faster — 335k active voxels: ~320 ms → ~10 ms — with bit-identical results (same coords, values, dtype, shape, and ordering). Re-verified against this PyPI wheel: compiled == pure-Python fallback.
  • Same public API, transparent. No new method; falls back to the pure-Python callback when the extension isn't built, exactly like get_many/set_many — one API, fast path + fallback.
  • Concurrent calls from multiple threads are serialised with a lock (the native callback ABI carries no user-data pointer, so the collector uses module state); the pure-Python fallback needs no lock.

Implemented in #4.

Install

pip install -U picopie            # core
pip install -U "picopie[web]"     # + the web viewer

The CycloneDX SBOM (sbom.cdx.json) is attached.

picopie 0.6.0 — compiled/native implicit callbacks

Choose a tag to compare

@Borderliner Borderliner released this 02 Jul 19:40
v0.6.0

Added — compiled callbacks for render_implicit_ / intersect_implicit_

render_implicit_(sdf, bbox) and intersect_implicit_(sdf) now accept a compiled SDF in addition to a plain Python callable. Pass a numba.cfunc or any ctypes function pointer with the ABI float(const PKVector3*) (a pointer to three contiguous float32) and it is handed straight to the native loop — no per-voxel Python round-trip.

import numba
from numba import types

sig = types.float32(types.CPointer(types.float32))   # matches PKPFnfSdf

@numba.cfunc(sig, nopython=True)
def my_sdf(p):
    return (p[0]**2 + p[1]**2 + p[2]**2) ** 0.5 - 8.0

part.render_implicit_(my_sdf, bbox)   # detected and run natively

Measured ~30× faster than the Python-callback path (compiled C sphere SDF at 0.2 mm voxels: 724 ms → 23 ms), with bit-identical geometry — verified again against this PyPI wheel (native 2145.6 == python 2145.6 mm³).

  • Plain sdf(x, y, z) callables are unchanged and keep the never-abort finite guard. Detection is duck-typed, so numba stays an optional, undeclared dependency — works equally with numba, a hand-written C shared library, or cffi.
  • Caveat: the compiled path deliberately bypasses the finite/exception guard (which is what makes the Python path both safe and slow). A compiled callback owns its own correctness — returning NaN/inf injects a zero-distance surface, matching upstream C# PicoGK. See "Compiled callbacks" in docs/tutorials/advanced/01-performance.md.
  • Requested in #1; implemented in #2.

Install

pip install -U picopie            # core
pip install -U "picopie[web]"     # + the web viewer

The CycloneDX SBOM (sbom.cdx.json) is attached.

v0.5.0 — rename import namespace picogk → picopie (LEAP 71 request)

Choose a tag to compare

@Borderliner Borderliner released this 02 Jul 14:54
v0.5.0
1fe6441

Breaking change: the import namespace is now picopie (was picogk)

At the request of LEAP 71 (PicoGK's maintainers — who commended the project as
"a high-quality and substantial project" but asked for clear separation from the
official library), PicoPie now consistently uses the PicoPie name in package,
namespace, and type names. This is an independent, community-maintained binding
not an official LEAP 71 project, and not affiliated with or endorsed by them.

Migrating

- import picogk
- from picogk import Voxels
- from picogk.shapes import Sphere
- from picogk.web import show
+ import picopie
+ from picopie import Voxels
+ from picopie.shapes import Sphere
+ from picopie.web import show
  • The exception type PicoGKError is renamed to PicoPieError.
  • The PyPI package name is unchangedpip install -U picopie.
  • The bundled native PicoGK runtime is unchanged (it is the actual PicoGK
    runtime, so it stays picogk.so internally); geometry, performance, and the
    whole API surface are otherwise identical to 0.4.2.

README and NOTICE now state clearly that PicoPie is unofficial and not affiliated
with LEAP 71. 436 CI tests pass on the renamed package.

Install

pip install -U picopie            # core
pip install -U "picopie[web]"     # + the web viewer

The CycloneDX SBOM (sbom.cdx.json) is attached.

v0.4.2 — post-construction step-bump fix + coverage

Choose a tag to compare

@Borderliner Borderliner released this 29 Jun 18:59
v0.4.2
aa8dd59

A small fix-and-coverage release closing the last items from the gap audit.

Fixed

  • Shape tessellation now follows post-construction modulation. Setting a
    modulated dimension after a shape is built — box.width = fn,
    cylinder.radius = fn, pipe.inner_radius / outer_radius = fn (and Cone) —
    now raises the tessellation step count to match the constructor path. It
    previously stayed silently coarse. Step counts are computed lazily from the
    current modulation state; an explicit *_steps argument still overrides, and
    constructor-path results (and C# parity) are unchanged.

Testing

  • Added direct coverage for previously-untested public wrappers
    (Voxels.voxel_size_mm / bounding_box, Lattice / VdbFile.is_valid, field
    memory_bytes, Metadata.to_dict, the VdbFile.save failure path, and the
    picogk.__all__ re-exports) and shape branches (spherical frame alignment, the
    cylindrical control-spline tangential step, closed control surfaces,
    LatticeManifold(extend_both_sides=...), the down-facing painter split, and
    mesh STL export). 436 CI tests.

Install

pip install -U picopie            # core
pip install -U "picopie[web]"     # + the web viewer

The CycloneDX SBOM (sbom.cdx.json) is attached.

v0.4.1 — web viewer polish (geometry/style split, matrix parity, camera) + validation guards

Choose a tag to compare

@Borderliner Borderliner released this 29 Jun 17:46
v0.4.1
dee92a2

A polish release on the 0.4.0 web viewer, from a final gap audit. The core was
verified — empirically, in isolated subprocesses — to have no crash/hang gaps;
the real findings were concentrated in the (newest) web viewer.

Fixed — web viewer

  • Matrix convention now matches the desktop Viewer (row-major,
    System.Numerics). A non-symmetric set_group_matrix / set_object_matrix
    previously rendered transposed in the browser.
  • The camera no longer re-fits on every update — recolouring, toggling
    visibility, or transforming a group preserves the current orbit (it auto-frames
    only on first load and on reset_view).
  • export_html now carries per-object transforms; the identity matrix is no
    longer a shared-mutable default.

Changed — web viewer

  • geometry/style split — heavy vertex/index buffers are separated from light
    per-object style (color, material, visibility, transform), so a style tweak does
    a cheap in-place update instead of re-transmitting and rebuilding all geometry.

Hardening (core)

  • Voxels.mesh_shell, ScalarField/VectorField set_many/get_many,
    ScalarField.slice, and Mesh.add_triangle now reject non-finite /
    out-of-range input with a clear error, consistent with the rest of the API
    (previously: silent garbage — none of these crashed).

Testing

  • Assert the require_finite / to_vec3 / bounds guards actually raise; add
    library-lifecycle tests; bring the web serialization and viewer camera-state
    math into per-wheel CI. 420 CI tests.

Install

pip install -U picopie            # core
pip install -U "picopie[web]"     # + the web viewer

The CycloneDX SBOM (sbom.cdx.json) is attached.

v0.4.0 — browser web viewer (three.js + anywidget)

Choose a tag to compare

@Borderliner Borderliner released this 29 Jun 14:07
v0.4.0
f60a2f6

The last big capability: a browser-based 3D viewer, so PicoPie now renders
where the desktop GLFW viewer can't — JupyterLab, VS Code notebooks, Google
Colab, and remote/SSH sessions.

Added — picogk.web

A three.js viewer inside an anywidget. Geometry is
computed in Python and streamed to the browser as binary buffers
(compute-in-Python, render-in-browser — not a WASM port of the kernel). Install
the optional extra:

pip install "picopie[web]"
import picogk
from picogk.web import show
picogk.init(0.2)
show(picogk.Voxels.sphere(radius=12))      # renders inline in a notebook cell
  • WebViewer at full parity with the desktop Vieweradd
    (Voxels/Mesh/PolyLine), remove, set_group_material, set_group_visible,
    set_background, set_group_matrix / set_object_matrix, reset_view,
    screenshot — plus a show(*objects) one-liner.
  • three.js renderer: PBR materials + lighting, orbit/pan/zoom, an auto-framed
    camera, a wireframe toggle, and keyboard shortcuts (F fit · W wireframe
    · S save PNG).
  • export_html(objects, path) — writes a self-contained, double-click-to-open
    HTML
    (the renderer is inlined and the geometry embedded); no Jupyter or server
    needed. Try python examples/web/demo.py.

Needs a browser with internet (three.js loads from a CDN the first time, then is
cached). The core library and the desktop viewer are unchanged.

Install

pip install picopie==0.4.0          # core
pip install "picopie[web]==0.4.0"   # + the web viewer

The CycloneDX SBOM (sbom.cdx.json) is attached.

v0.3.2 — project_z_slice_ fine-voxel fix + voxel-size test coverage

Choose a tag to compare

@Borderliner Borderliner released this 27 Jun 07:34
v0.3.2
0cf41e7

A follow-up to 0.3.1: found and fixed another instance of the same bug class
(a millimetre value used as an integer voxel count) by auditing the runtime,
and closed the test-coverage gap that let the class ship twice.

Fixed

  • project_z_slice_ at fine voxel sizes. PicoGK's ProjectZSliceDn /
    ProjectZSliceUp sealed the end cap by iterating (int)(0.5 + background_mm)
    slices — but the background is in mm (narrowBand × voxel_size), not a
    voxel count. Below ~0.167 mm it truncated to 0, so the bottom cap was never
    sealed and the projected solid came out non-watertight — silently, with no
    error (re-voxelising it collapsed the volume, e.g. 818 → 22 mm³ at 0.1 mm).
    Above ~1.5 mm it over-iterated. The bundled runtime now uses the narrow band
    directly, so the result is consistent across voxel sizes.
  • Voxels.triple_offset_ and project_z_slice_ now reject non-finite (NaN/inf)
    arguments with a ValueError, matching offset_ / double_offset_.

Testing

  • New voxel-size sweep tripwire (tests/test_voxel_size_sweep.py, runs per
    wheel) exercises the resolution-sensitive native ops across 0.1–1.0 mm and
    asserts the results stay valid and consistent with the 0.5 mm baseline. The
    whole suite previously ran only at 0.5 mm — the one resolution where these
    narrow-band truncations can't fire — which is why the class shipped twice.
  • scripts/fuzz_abort.py now sweeps voxel size across workers (0.05–2.0 mm) and
    fuzzes the previously-uncovered triple_offset_, project_z_slice_, and
    mesh_shell ops. scripts/voxel_size_sweep.py is the diagnostic that found it.

Install

pip install picopie==0.3.2

The CycloneDX SBOM (sbom.cdx.json) is attached.

v0.3.1 — implicit intersect fix at fine voxel sizes + smoother gallery

Choose a tag to compare

@Borderliner Borderliner released this 27 Jun 06:29
v0.3.1
cfd9ab0

A bugfix + polish release on top of the 0.3.0 ShapeKernel port.

Fixed

  • Implicit intersect at fine voxel sizes. Voxels.intersect_implicit_ (and
    the ImplicitGyroid / ImplicitSphere / … intersect helpers) aborted with
    "expected grid A outside value > 0, got 0" whenever the voxel size was below
    ~0.33 mm. Upstream PicoGK's IntersectImplicit built its temporary grid from
    the background in millimetres (a float = narrowBand × voxel_size) passed
    into an int nNarrowBand argument, which truncated to 0 at fine resolutions
    → a grid with background 0 → OpenVDB's csgIntersection rejected it. The
    bundled runtime is now patched at build time to pass the source's narrow band
    instead, so implicit intersects work at any voxel size.

Changed

  • The example gallery (examples/shapekernel/gallery.py) now renders at a
    0.2 mm voxel size by default (was 0.5 mm) with a new --voxel-size flag,
    and the small implicit shapes are scaled up — the docs gallery images are
    noticeably smoother (no faceted silhouettes / "orange-peel"). Surface
    smoothness is set by the voxel size, not the parametric tessellation.

Install

pip install picopie==0.3.1

The CycloneDX SBOM (sbom.cdx.json) is attached.

PicoPie 0.3.0 — ShapeKernel port

Choose a tag to compare

@Borderliner Borderliner released this 26 Jun 19:56
v0.3.0
432ed02

picogk.shapes — a full, Pythonic port of LEAP 71's ShapeKernel (pinned ShapeKernel-v2.1.0), built on the PicoPie core and parity-tested vs the reference C# (geometry to float precision).

Added

  • Support layer: LocalFrame/Frames, LineModulation/SurfaceModulation, vector/spline/list/grid/formula utilities, splines (ControlPointSpline/Surface, Tangential/CylindricalControlSpline).
  • All 10 base shapes: Sphere, Box, Cylinder, Cone, Ring, Lens, Pipe, PipeSegment, Revolve, LogoBox — frames + modulations + spines, to_voxels()/to_mesh().
  • Lattices (LatticePipe/LatticeManifold) + builders; implicit SDFs (ImplicitGyroid/Sphere/Genus/SuperEllipsoid) with render/intersect.
  • Measurement (volume/area/centre-of-gravity/inertia), mesh utilities, CSV/STL/VDB export, colour palette/scales + MeshPainter.
  • Runnable example gallery + a "Shapes" tutorial track + docs gallery.

Fixed / hardened

  • Mesh.from_arrays and Lattice.add_* reject non-finite input with a clear ValueError (both fast + fallback paths) — every shape validates its dimensions up front.
  • B-splines with too few control points raise a clear error instead of ZeroDivisionError.

Install: pip install picopie==0.3.0 (or uv add picopie). Self-contained wheels for CPython 3.10–3.13 on Linux/macOS/Windows. See the CHANGELOG.

picopie 0.2.1 — first public release

Choose a tag to compare

@Borderliner Borderliner released this 25 Jun 15:50
v0.2.1
0c77a2a

First public release of PicoPie — a Pythonic binding for PicoGK
(LEAP 71's OpenVDB voxel/level-set kernel). No .NET, no compiler, no system libraries.

pip install picopie          # or: uv add picopie
pip install "picopie[viz]"   # + headless slice/mesh PNG helpers

Self-contained wheels for CPython 3.10–3.13 on Linux (manylinux x86-64), macOS (Apple Silicon),
and Windows (x64)
— the native runtime (OpenVDB 13, PicoGK 26.2) and all its C++ deps are bundled.

Highlights

  • Voxels (primitives, booleans + - &, offsets, shell_, implicit SDF, queries), Mesh
    (STL/OBJ in/out, NumPy arrays), Lattice, ScalarField/VectorField, Metadata, VDB I/O.
  • Interactive viewer (picogk.show, render_png) + headless slice/mesh PNG helpers.
  • Compiled fast path (~13–28× bulk transfer) with pure-Python fallback.

Reliability

  • Parity-validated against C# PicoGK on the same runtime (volumes, dims, mesh counts, queries).
  • Never aborts — native/OpenVDB errors surface as catchable PicoGKError; non-finite inputs
    rejected up front (fuzz-verified). Green CI on all three OSes; ~190 tests; mypy + ruff clean.
  • Reproducible & auditable: every dep version-pinned; ships an SBOM + hash-pinned build deps.

Docs

Leveled tutorials (Novice / Intermediate / Advanced) + a one-file QuickLearn — see
docs/.

PyPI: https://pypi.org/project/picopie/0.2.1/ · Apache-2.0.