This document describes the proper method for generating accurate involute spur gears in FreeCAD using Python, based on standard gear theory and CAD best practices.
The involute of a circle is the curve traced by a point on a taut string as it unwinds from a circle (the base circle).
Parametric Equations:
# For a base circle of radius rb, at unwrap angle theta:
x = rb * (cos(theta) + theta * sin(theta))
y = rb * (sin(theta) - theta * cos(theta))Reference: Dudley's Handbook of Practical Gear Design, Chapter 2
For a spur gear with module m, number of teeth z, and pressure angle α:
# Basic dimensions (ISO 53:1998)
pitch_diameter = m * z
base_diameter = pitch_diameter * cos(α)
addendum_diameter = pitch_diameter + 2 * m
dedendum_diameter = pitch_diameter - 2 * 1.25 * m
# Tooth thickness at pitch circle
tooth_thickness = (π * m) / 2Standard Values:
- Pressure angle: 20° (most common), 14.5° (older), 25° (heavy duty)
- Module: 0.5mm to 25mm (depends on application)
The proper CAD approach uses separate geometric entities, not a single interpolated curve:
- Right Involute Curve - Generate as multiple small line segments or as a proper involute equation curve
- Tip Land - Circular arc at addendum radius
- Left Involute Curve - Mirror of right side
- Root Fillet - Circular arc or trochoid curve at dedendum
Key Insight: Most CAD systems (SolidWorks, Fusion 360, etc.) build gear teeth using:
- Equations for involute curves (if supported)
- OR many small line segments approximating the involute
- Proper geometric constraints between segments
- Mirror operations for symmetry
Interpolating a single BSpline through all points causes issues:
- BSpline interpolation adds unwanted curvature
- Periodic BSplines have complex mathematical requirements
- Doesn't accurately represent the involute curve
The involute IS the exact curve - approximating it with a different curve type defeats the purpose.
import Part
import FreeCAD as App
def createInvoluteToothProfile(module, teeth, pressure_angle_deg):
"""
Create tooth profile using polygon approximation of involute.
Returns a closed Wire object.
"""
# Calculate dimensions
pitch_dia = module * teeth
base_dia = pitch_dia * math.cos(math.radians(pressure_angle_deg))
addendum_dia = pitch_dia + 2 * module
dedendum_dia = pitch_dia - 2 * 1.25 * module
# Generate involute points
points = []
# Right flank - involute curve
for i in range(20):
theta = theta_root + (i/19) * (theta_tip - theta_root)
x, y = involute_point(base_radius, theta)
# Rotate to position
points.append(App.Vector(x_rotated, y_rotated, 0))
# Tip land - arc
for i in range(5):
angle = angle_right_tip + (i/4) * (angle_left_tip - angle_right_tip)
x = addendum_radius * math.cos(angle)
y = addendum_radius * math.sin(angle)
points.append(App.Vector(x, y, 0))
# Left flank - involute curve (reverse)
# ... similar to right flank
# Root land - arc
# ... close the profile
# Create wire from points
wire = Part.makePolygon(points)
return wireimport Sketcher
def createConstrainedToothSketch(sketch, module, teeth, pressure_angle):
"""
Create tooth profile using sketcher constraints.
This is closer to manual CAD modeling.
"""
# Add construction circle for base circle
base_circle = sketch.addGeometry(Part.Circle(...), True)
# Add involute as multiple small line segments
prev_point_id = -1
for i in range(20):
# Calculate involute point
line = sketch.addGeometry(Part.LineSegment(...))
if prev_point_id >= 0:
sketch.addConstraint(Sketcher.Constraint('Coincident',
prev_point_id, 2, line, 1))
prev_point_id = line
# Add tip arc
tip_arc = sketch.addGeometry(Part.ArcOfCircle(...))
sketch.addConstraint(Sketcher.Constraint('Coincident', ...))
sketch.addConstraint(Sketcher.Constraint('Radius', tip_arc, addendum_radius))
# Continue for left side and root...# WRONG - causes "Standard_ConstructionError"
profile.append(profile[0]) # Duplicate!
bspline.interpolate(profile, PeriodicFlag=True)# WRONG - BSpline is not an involute!
bspline.interpolate(involute_points) # Introduces unwanted curvature# WRONG - polar pattern handles spacing
angular_pitch = 2*pi / teeth
profile_covers_full_angular_pitch # Don't do this!Correct: Generate only the tooth outline. The polar pattern creates the gaps.
# WRONG - forgetting the involute function
angle = theta # Missing inv(α) term!
# CORRECT
angle = theta + inv_alpha - theta_pitch + half_tooth_angledef generateSpurGear(doc, module, teeth, pressure_angle, height):
"""
Proper spur gear generation following CAD best practices.
"""
# 1. Calculate all dimensions first
dimensions = calculate_gear_dimensions(module, teeth, pressure_angle)
# 2. Create body
body = doc.addObject('PartDesign::Body', 'spur_gear')
# 3. Create sketch
sketch = doc.addObject('Sketcher::SketchObject', 'ToothProfile')
body.addObject(sketch)
# 4. Generate tooth profile as POLYGON (not spline!)
tooth_points = generate_involute_tooth_points(dimensions)
# 5. Add polygon to sketch as connected line segments
add_polygon_to_sketch(sketch, tooth_points)
# 6. Pad the tooth
pad = doc.addObject("PartDesign::Pad", "Tooth")
body.addObject(pad)
pad.Profile = sketch
pad.Length = height
# 7. Polar pattern
polar = body.newObject('PartDesign::PolarPattern', 'Teeth')
polar.Originals = [pad]
polar.Angle = 360
polar.Occurrences = teeth
return bodyinv(α) = tan(α) - α (in radians!)
theta = sqrt((r/rb)² - 1)
where rb = base radius
half_tooth_angle = (π*m/2) / pitch_radius
At the pitch circle, the involute must be positioned such that:
angle_at_pitch = ±half_tooth_angle
Since involute has unwrapped by theta_pitch at pitch radius:
rotation_offset = half_tooth_angle + inv(α) - theta_pitch
- Tooth count - Count teeth = specified number
- Pitch circle - Measure pitch diameter = module × teeth
- Tooth thickness - At pitch circle ≈ π×module/2
- Involute curve - Should be smooth, no kinks
- Profile closure - No gaps in tooth outline
# Generate two gears that should mesh
gear1 = generateSpurGear(doc, module=2, teeth=20, ...)
gear2 = generateSpurGear(doc, module=2, teeth=40, ...)
# Position for meshing
center_distance = module * (20 + 40) / 2 # = 60mm for m=2
# Place gear2 at (60mm, 0, 0)
# Rotate gear2 by: 180° / 40 teeth = 4.5°- Dudley's Handbook of Practical Gear Design and Manufacture - Darle W. Dudley
- ISO 53:1998 - Cylindrical gears for general and heavy engineering — Standard basic rack tooth profile
- ANSI/AGMA 2001-D04 - Fundamental Rating Factors and Calculation Methods for Involute Spur and Helical Gear Teeth
- Machinery's Handbook - Section on Gears
-
Abandon BSpline approach - Use Part.makePolygon() instead
-
Generate accurate involute points - Use proper formulas
-
Use Sketcher line segments - For better CAD compatibility
-
Add proper geometric constraints - If using Sketcher
-
Test with known gear dimensions - Validate against standards
For users who prefer to have full manual control over the tooth shape, or for creating custom non-involute profiles, it is possible to sketch the tooth profile directly in the Sketcher workbench. This approach provides great flexibility but requires careful application of constraints to ensure a valid and accurate profile.
Here is a step-by-step guide to manually sketching a single gear tooth, which can then be padded and patterned.
First, create the key reference circles as construction geometry. These will guide the placement of the tooth profile.
-
Open the Sketcher Workbench and create a new sketch on the XY plane.
-
Using the Create Circle tool, draw four concentric circles centered at the origin (0,0).
-
Select all four circles and toggle them to Construction Mode.
-
Add Diameter constraints to each circle corresponding to the gear's dimensions:
-
Addendum Circle (Tip Circle)
-
Pitch Circle
-
Base Circle
-
Dedendum Circle (Root Circle)
-
Example Python Code:
import FreeCAD as App
import Sketcher
import math
# Example dimensions for a Module 2, 20-tooth gear
module = 2.0
num_teeth = 20
pressure_angle = 20.0
pitch_dia = module * num_teeth
base_dia = pitch_dia * math.cos(math.radians(pressure_angle))
addendum_dia = pitch_dia + 2 * module
dedendum_dia = pitch_dia - 2 * 1.25 * module
# Get the active sketch
sketch = App.ActiveDocument.ActiveSketch
# Add construction circles
c_add = sketch.addGeometry(Part.Circle(App.Vector(0,0,0), App.Vector(0,0,1), addendum_dia/2), True)
sketch.addConstraint(Sketcher.Constraint('Diameter', c_add, addendum_dia))
c_pitch = sketch.addGeometry(Part.Circle(App.Vector(0,0,0), App.Vector(0,0,1), pitch_dia/2), True)
sketch.addConstraint(Sketcher.Constraint('Diameter', c_pitch, pitch_dia))
c_base = sketch.addGeometry(Part.Circle(App.Vector(0,0,0), App.Vector(0,0,1), base_dia/2), True)
sketch.addConstraint(Sketcher.Constraint('Diameter', c_base, base_dia))
c_ded = sketch.addGeometry(Part.Circle(App.Vector(0,0,0), App.Vector(0,0,1), dedendum_dia/2), True)
sketch.addConstraint(Sketcher.Constraint('Diameter', c_ded, dedendum_dia))The involute curve can be approximated by a 3-point arc or a series of small line segments. For simplicity, we'll use an arc here.
-
Create a 3-Point Arc.
-
Place the start point of the arc on the Base Circle.
-
Place the end point of the arc on the Addendum Circle.
-
Place the third point somewhere between the start and end to give the arc its curve.
-
Add a Tangent constraint between the arc and the Base Circle at the start point. This is crucial for a correct involute approximation.
-
Create another 3-Point Arc for the tooth tip.
-
Constrain the start point of this arc to be Coincident with the end point of the right flank arc.
-
Constrain the arc to be tangent to the Addendum Circle. In practice, it's easier to make the arc's endpoints symmetric with respect to the Y-axis and coincident with the addendum circle.
-
Select the right flank arc.
-
Use the Mirror tool.
-
Select the Y-axis as the mirror axis.
-
This creates the left flank of the tooth.
-
Create a Fillet (or a small arc) between the start of the right flank (on the base circle) and the dedendum circle.
-
Do the same for the left flank.
-
Alternatively, draw a single arc for the root, connecting the start points of the two flanks, and make it tangent to both.
-
Ensure all points are connected with Coincident constraints to form a closed loop.
-
Add a Symmetry constraint to the start and end points of the tip land arc with respect to the Y-axis.
-
Add a Dimension constraint for the tooth thickness at the pitch circle. A simple way is to add a horizontal distance constraint between the points where the flanks intersect the pitch circle.
tooth_thickness = (math.pi * module) / 2
This manual process gives you a fully constrained sketch of a single tooth. You can then exit the sketch, use Pad to give it thickness, and finally use a Polar Pattern to create the full gear.
The article explains how to model accurate involute spur gears in SOLIDWORKS using global variables and parametric equations, which is crucial for simulations or non-traditional manufacturing. It details setting up primary parameters like diametral pitch, pressure angle, and number of teeth, along with secondary parameters for face width and bore diameter. The core steps involve sketching a gear blank, defining the tooth profile with an equation-driven involute curve, and then patterning these features to create a dynamic gear model.
Source: How to Model Accurate Involute Spur Gears in SOLIDWORKS