Code Library
Rhino & GrasshopperPythonRhino 6–8 + Grasshopper · GhPython componentMIT licenseAdvanced

Grinding-wheel pivot-angle clearance check (Grasshopper Python)

The full version of this problem — from the grinding-wheel pivot-angle post — models the wheel pack as real solids and sweeps the angle against the tool, blank, and machine envelope. This is the core geometric idea distilled into one GhPython component: given a pivot point, an arm length, a wheel radius, and a candidate angle, it checks whether the wheel clears a 2D tool profile — wire angle_deg to a slider and watch clears flip in real time.

Before you run it

  • Rhino 6–8 with Grasshopper, dropped into a GhPython Script component
  • Component inputs named profile (Curve), pivot (Point), arm (Number), wheel_rad (Number), angle_deg (Number)
  • This is a simplified 2D clearance check — a production pivot-angle system also needs the wheel pack's geometry and the machine envelope, not just one wheel circle

The code

GitHub
"""GhPython component: checks whether a grinding wheel clears a 2D tool
profile at a candidate pivot angle.

Inputs:
  profile   - Curve, the tool profile in the grinding plane
  pivot     - Point3d, the wheel's pivot point
  arm       - float, distance from pivot to wheel center
  wheel_rad - float, wheel radius
  angle_deg - float, candidate pivot angle (wire to a slider)

Outputs:
  clears     - bool, True if the wheel does not intersect the profile
  wheel_ctr  - Point3d, the wheel center at this angle (for previewing the wheel)
  clearance  - float, distance from wheel center to the profile minus wheel_rad
               (positive = clear, negative = the wheel would cut into the profile)
"""

import math
import Rhino.Geometry as rg

SAMPLES = 300


def wheel_center(pivot, arm, angle_deg):
    a = math.radians(angle_deg)
    return rg.Point3d(pivot.X + arm * math.cos(a), pivot.Y + arm * math.sin(a), pivot.Z)


def min_distance_to_profile(curve, point, samples):
    t0 = curve.Domain.T0
    t1 = curve.Domain.T1
    best = None
    for i in range(samples + 1):
        t = t0 + (t1 - t0) * i / samples
        pt = curve.PointAt(t)
        d = pt.DistanceTo(point)
        if best is None or d < best:
            best = d
    return best


wheel_ctr = wheel_center(pivot, arm, angle_deg)
clearance = min_distance_to_profile(profile, wheel_ctr, SAMPLES) - wheel_rad
clears = clearance >= 0

What you get

What you get

Wired to a Grasshopper number slider on angle_deg, the "clears"
output flips from True to False in real time as you drag through
the angle range - the same "watch collisions resolve live" behavior
described in the pivot-angle blog post, on a simplified 2D profile.

How it works

  • Grasshopper Python components read inputs and write outputs by name, matching whatever you named the component's parameters — there's no def main() or argument parsing, just the variable names profile, pivot, arm, wheel_rad, angle_deg appearing already populated.
  • Rhino.Geometry, not rhinoscriptsyntax, is the right import inside a GH component — components operate on the geometry objects Grasshopper hands them, not on the active document, which is what rhinoscriptsyntax is built for.
  • Sampling the profile curve at 300 points and taking the minimum distance to the wheel center is the same brute-force-but-reliable technique as the standalone Rhino curvature-finder script — good enough for live slider feedback, not certification-grade clearance analysis.
  • clearance = min_distance - wheel_rad turns one number into the whole answer: positive means clear, negative means the wheel would cut into the profile at this angle — wire that straight to a boolean toggle or a colored preview.

Gotchas & honest limits

  • This is the simplified 2D version of the real problem: a production pivot-angle check needs the wheel pack's full solid geometry and the machine's envelope, not just one wheel circle against a flat profile — this component demonstrates the core geometric idea, not the full system.
  • 300 samples is a compromise for live slider feedback — moving the slider re-runs the check every frame, so this favors speed over the sampling density the standalone curvature-finder script uses.
  • The wheel is modeled as a single circle at wheel_ctr — a real wheel has width and a wheel pack behind it; both can collide even when the leading-edge circle checked here clears.
  • Treat a clears = True result as "worth checking on the real setup," not as a substitute for the actual collision check your grinding software runs before cutting.

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é