curvature op• Data kinds: points → descriptor
• Call: import fullseye as fs; fs.ledger.shape_index(points, k=25, normals=None) (to call the implementation directly, import curvature3d; curvature3d.shape_index(points, k=25, normals=None); from the registry, ops3d.get("shape_index"))
Koenderink's shape index s∈[-1,1] (convex sphere +1, cylinder +0.5, saddle 0, concave sphere −1). → (N,).
The umbilic/plane decision is relative to the curvature scale (no absolute threshold). Gentle convex/concave regions (even with tiny curvature) keep their sign = concave/convex, and only points whose curvature is 0 relative to the curvature scale of the whole data get s=0 as planes.
normals (oriented reference normals, (N,3)): when omitted, the concave/convex sign of an open surface is undefined (reported as convex magnitude). Passing oriented normals aligns with the global orientation and yields the correct sign (concave sphere = cup → -1).
Computation (per point, same fit as principal_curvatures):
• Plane test: if the curvedness sqrt((k1² + k2²) / 2) is below the median of the curvedness over all points × 1e-3, then s = 0. If the median is 0 (no curvature signal), all points are 0.
• Umbilic test: if |k1 - k2| < 1e-2 × (|k1| + |k2|), then s = sign(k1 + k2) (exactly ±1).
• Otherwise: s = (2/π) · arctan((k1 + k2) / (k1 - k2)).
• The threshold is not absolute but relative to the curvature scale of the whole data, so even for the same shape, which points are treated as planar changes with how they are mixed with other points. Use it on the premise of classifying a single point cloud.
• Points with fewer than 5 neighbours get k1 = k2 = 0 → plane (0). k is truncated to N-1.
• normals must be (N,3) with finite, non-zero rows (ValueError). When omitted, the sign of an open surface is undefined (convex side).
• The strength of bending is not included. If you also need the strength, stack the 2 values of principal_curvatures into (N,2) and pass them through curvature_to_shape_index.
• blas_threads_and_memory — Why matrix decompositions are slow — BLAS threads, caches, memory layout
• Sample-data catalog (download URLs / licences) — 2-D uses skimage.data (BSD/public domain) plus synthetic images; 3-D lists download URLs for real data sources (Stanford, PDS, …).
• Operator provenance and references — the sources of the research/methods this op family came from.
• curvature_grasp — py -3.11 examples_3d/curvature_grasp.py
• itokawa_curvature — py -3.11 examples_3d/itokawa_curvature.py
descriptor as input)fuse_to_voxel · shape_distance
curvature)principal_curvatures · mean_curvature · gaussian_curvature · estimate_normals
*Provenance: curvature3d.py — 3D operator registry. This per-op note is generated by tools/opdocs.py md (do not hand-edit).*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.