Code Library
Rhino & GrasshopperPythonRhino 6–8 · built-in Python (rhinoscriptsyntax)MIT license

Find the tightest radius on any curve in Rhino (Python)

Before you program a cutter along a curve — a cam profile, a grinding-wheel path, an imported spline from a customer file — one number decides which tools are even possible: the tightest radius on that curve. A tool with a bigger radius gouges; a corner radius you didn't notice becomes a dwell mark. This script samples the curve densely, finds the minimum radius of curvature, drops a point and a labeled text dot on the exact spot, and prints the largest tool diameter that can follow the curve without gouging.

Before you run it

  • Rhino 6, 7, or 8 (script uses only rhinoscriptsyntax)
  • Run via EditPythonScript (Rhino 6/7) or the ScriptEditor (Rhino 8)

The code

GitHub
"""Find the tightest radius on a curve - before your toolpath does.

Rhino 6/7: Tools > PythonScript > Edit, paste, run.
Rhino 8:   ScriptEditor (Python 2/3 both fine - this is plain rhinoscriptsyntax).
"""

import rhinoscriptsyntax as rs

SAMPLES = 500  # more = finer scan; 500 is plenty for most curves


def main():
    curve = rs.GetObject("Select a curve to analyze", rs.filter.curve)
    if not curve:
        return

    t0, t1 = rs.CurveDomain(curve)

    min_radius = None
    min_param = None

    for i in range(SAMPLES + 1):
        t = t0 + (t1 - t0) * i / SAMPLES
        cc = rs.CurveCurvature(curve, t)
        if cc is None:            # straight section: no curvature here
            continue
        radius = cc[3]
        if min_radius is None or radius < min_radius:
            min_radius = radius
            min_param = t

    if min_radius is None:
        print("Curve is straight everywhere - no finite radius.")
        return

    pt = rs.EvaluateCurve(curve, min_param)
    rs.AddPoint(pt)
    rs.AddTextDot("R min = {:.3f}".format(min_radius), pt)

    print("Tightest radius: {:.3f} at parameter {:.4f}".format(min_radius, min_param))
    print("Largest non-gouging tool: {:.3f} dia (concave side).".format(2 * min_radius))


main()

How it works

  • rs.CurveDomain gives the parameter range; the loop walks it in SAMPLES even steps — parameter-space sampling, simple and good enough for a scan.
  • rs.CurveCurvature(curve, t) returns point, tangent, center, radius, and curvature vector at the parameter; index [3] is the radius. On straight sections curvature is zero and the call returns None, which the loop just skips.
  • The winner gets rs.AddPoint + rs.AddTextDot, so the answer is on the geometry where a programmer will actually see it, not buried in a console.
  • 2 × R min is the largest cutter that can ride the concave side without gouging — the number you take to CAM.

Gotchas & honest limits

  • Sampling can miss a spike between samples on pathological curves; for certification-grade analysis use Rhino's CurvatureGraph alongside. For tool selection, 500 samples is plenty.
  • The gouge limit applies to concave regions relative to your cut side. A convex-only curve doesn't limit tool size.
  • Polylines have zero radius at their kinks — the script will (correctly) report ~0 at a corner. Fillet first, then re-scan.
  • Works on planar and 3D curves alike; for 3D remember the radius is measured in the osculating plane, not in your machining plane.

Goes deeper

Want this adapted to your shop — or built into a real tool?

Samples are the free 80%. The last 20% is the part I do for a living.

Get in touch
Home
Blog
Tools
Code
Email
LinkedIn
Résumé