Create an involute spur gear using FreeCAD's Part module.
Scanned 5/27/2026
Install via CLI
openskills install ghbalf/freecad-ai# Spur Gear Generator
Create an involute spur gear using FreeCAD's Part module.
## Parameters to extract from user request
- **Module** (m): tooth size parameter, default 2.0mm
- **Number of teeth** (z): default 20
- **Pressure angle**: default 20 degrees
- **Face width** (thickness): default 10mm
- **Bore diameter**: center hole, default 5mm (0 = no bore)
## Derived dimensions
- Pitch diameter: d = m * z
- Tip diameter: da = m * (z + 2)
- Root diameter: df = m * (z - 2.5)
## Construction
Use `execute_code` with the complete gear generation code below.
Replace the parameter values at the top with the user's requested values.
```python
import math
import Part
import FreeCAD as App
# === PARAMETERS (replace with user values) ===
module = 2.0
teeth = 20
pressure_angle_deg = 20
face_width = 10.0
bore_dia = 5.0
# === DERIVED ===
pitch_r = module * teeth / 2.0
base_r = pitch_r * math.cos(math.radians(pressure_angle_deg))
tip_r = pitch_r + module
root_r = pitch_r - 1.25 * module
def involute_pts(base_r, tip_r, n=20):
max_angle = math.sqrt((tip_r / base_r) ** 2 - 1)
pts = []
for i in range(n):
t = i * max_angle / (n - 1)
x = base_r * (math.cos(t) + t * math.sin(t))
y = base_r * (math.sin(t) - t * math.cos(t))
pts.append(App.Vector(x, y, 0))
return pts
def rotate_pt(pt, angle_rad):
c, s = math.cos(angle_rad), math.sin(angle_rad)
return App.Vector(c * pt.x - s * pt.y, s * pt.x + c * pt.y, 0)
def pt_angle(pt):
return math.atan2(pt.y, pt.x)
# Involute half-tooth thickness angle
inv_alpha = math.tan(math.radians(pressure_angle_deg)) - math.radians(pressure_angle_deg)
half_thick_angle = math.pi / (2 * teeth) + inv_alpha
# Generate involute profile for one tooth, centered on +Y axis
right_involute = involute_pts(base_r, tip_r, 20)
right_side = [rotate_pt(p, -half_thick_angle + math.pi / 2) for p in right_involute]
left_side = [App.Vector(-p.x, p.y, 0) for p in right_side]
# Key points
left_base, left_tip = left_side[0], left_side[-1]
right_base, right_tip = right_side[0], right_side[-1]
lb_a, rb_a = pt_angle(left_base), pt_angle(right_base)
# Points on root circle at flank angles
lb_on_root = App.Vector(root_r * math.cos(lb_a), root_r * math.sin(lb_a), 0)
rb_on_root = App.Vector(root_r * math.cos(rb_a), root_r * math.sin(rb_a), 0)
# Build closed tooth profile: root → left involute → tip arc → right involute → root arc
tooth_edges = []
# Radial: left root → left base
if lb_on_root.distanceToPoint(left_base) > 0.01:
tooth_edges.append(Part.LineSegment(lb_on_root, left_base).toShape())
# Left involute BSpline (base → tip)
bs_left = Part.BSplineCurve()
bs_left.interpolate(left_side)
tooth_edges.append(bs_left.toShape())
# Tip arc (left tip → right tip)
tip_mid_a = (pt_angle(left_tip) + pt_angle(right_tip)) / 2
tip_mid = App.Vector(tip_r * math.cos(tip_mid_a), tip_r * math.sin(tip_mid_a), 0)
tooth_edges.append(Part.Arc(left_tip, tip_mid, right_tip).toShape())
# Right involute BSpline (tip → base)
bs_right = Part.BSplineCurve()
bs_right.interpolate(list(reversed(right_side)))
tooth_edges.append(bs_right.toShape())
# Radial: right base → right root
if right_base.distanceToPoint(rb_on_root) > 0.01:
tooth_edges.append(Part.LineSegment(right_base, rb_on_root).toShape())
# Root arc (right root → left root, closing the profile)
root_mid_a = (lb_a + rb_a) / 2
root_mid = App.Vector(root_r * math.cos(root_mid_a), root_r * math.sin(root_mid_a), 0)
tooth_edges.append(Part.Arc(rb_on_root, root_mid, lb_on_root).toShape())
# Create one tooth solid
tooth_wire = Part.Wire(tooth_edges)
tooth_face = Part.Face(tooth_wire)
tooth_solid = tooth_face.extrude(App.Vector(0, 0, face_width))
# Build gear: base cylinder + all teeth fused together
gear = Part.makeCylinder(root_r, face_width)
for t in range(teeth):
rotated = tooth_solid.copy()
if t > 0:
rotated.rotate(App.Vector(0, 0, 0), App.Vector(0, 0, 1), t * 360.0 / teeth)
gear = gear.fuse(rotated)
gear = gear.removeSplitter()
# Cut bore hole
if bore_dia > 0:
bore = Part.makeCylinder(bore_dia / 2, face_width + 2, App.Vector(0, 0, -1))
gear = gear.cut(bore)
# Add to document
gear_obj = App.ActiveDocument.addObject("Part::Feature", "Gear_M{}_Z{}".format(module, teeth))
gear_obj.Label = "Gear M{} Z{}".format(module, teeth)
gear_obj.Shape = gear
App.ActiveDocument.recompute()
print("Gear created: pitch dia={:.1f}mm, tip dia={:.1f}mm, root dia={:.1f}mm".format(
pitch_r * 2, tip_r * 2, root_r * 2))
```
## Important
- Copy the COMPLETE code block above into `execute_code`, only changing the parameter values at the top
- Do NOT try to use PartDesign Body/Sketch for the gear — use Part::Feature directly
- Do NOT use `App.Gui` — it may not be available in the sandbox
- Label the gear clearly with its parameters: "Gear M2 Z24"
- The gear is centered at the origin
No comments yet. Be the first to comment!