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
"""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 >= 0What 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 namesprofile,pivot,arm,wheel_rad,angle_degappearing already populated. Rhino.Geometry, notrhinoscriptsyntax, is the right import inside a GH component — components operate on the geometry objects Grasshopper hands them, not on the active document, which is whatrhinoscriptsyntaxis 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_radturns 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 = Trueresult 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.