Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ncgears

ncgears generates noncircular gear pairs from a transmission law or a pitch-curve shape.

The generator creates 2D outlines, verifies the assembled pair for interference and contact-motion error, and exports CSV, SVG, DXF, JSON, PNG, and animated GIF files. It supports closed gears, finite open segments, deep nonconvex pitch curves, unequal ratios, and generalized-involute teeth. The complete application and geometry pipeline are implemented in Python; Shapely/GEOS provides robust floating-point polygon operations.

Animated crazy_kidney_bean gear pair

Project status: alpha. Generated geometry should be reviewed for the intended material, manufacturing process, load, speed, and tolerances.

Install

pip install ncgears

PNG, animated GIF, and interactive Matplotlib previews are optional:

pip install "ncgears[plot]"

Command line

Most functionality is available in the CLI:

ncgears "phi - 0.08*sin(2*phi)" --teeth 24 --module 1.5 \
  --name two_lobe --dxf two_lobe.dxf --render --gif --plot

ncgears "1 + 0.08*cos(2*phi)" --centrode --teeth 20 \
  --name centrode_two_lobe

# Offset every face inward by 0.04 module on each gear.
ncgears "phi - 0.08*sin(2*phi)" --clearance 0.04

# Or derive the offset for at most 1.5 degrees of driven-gear backlash.
ncgears "phi - 0.08*sin(2*phi)" --max-backlash 1.5

Run ncgears --help for all commonly used options.

Basic python usage

Describe the desired relationship between the drive angle phi and the driven angle. Here the driven gear speeds up and slows down twice per revolution while returning to the same 1:1 average ratio:

import ncgears

pair = ncgears.generate(
    "phi - 0.08*sin(2*phi)",
    teeth=24,
    module=1.5,
    name="two_lobe",
)

print(pair.summary())
pair.export_dxf("two_lobe.dxf")
pair.export_svg("two_lobe.svg")

DXF outlines are simplified by default to a maximum deviation of 0.001 module from the full-resolution generated path. Override this in module units with pair.export_dxf("two_lobe.dxf", max_error=0.0005) or --dxf-max-error 0.0005; use zero to export every generated point.

module and all exported coordinates use millimetres. The returned GearPair also provides:

pair.drive_outline           # (N, 2) NumPy array
pair.driven_outline          # centered on its own shaft
pair.placed_driven_outline   # translated into assembled position
pair.center_distance
pair.drive_teeth
pair.driven_teeth
pair.ratio
pair.maximum_transmission_error
pair.clearance                 # per-face inward offset / module
pair.minimum_backlash_deg      # total driven-gear angular free play
pair.maximum_backlash_deg
pair.metadata                 # complete verification report
pair.directory                # CSV and JSON source files
pair.render()                 # pair.png; requires ncgears[plot]
pair.render_gif()             # pair.gif; follows the generated motion law
pair.plot()                   # interactive motion slider, zoom, and pan

Pass plot=True to generate() or generate_from_centrode() to open the interactive plot as soon as generation finishes. The returned Matplotlib figure can also be embedded or customized without opening a window:

figure = pair.plot(show=False)
figure.suptitle("My mechanism")

The output directory defaults to out/<name>/. Each successful generation contains drive.csv, driven.csv, metadata.json, and the sampled input.

Clearance and backlash

Pass clearance to offset both finished gear solids inward, normal to every face. The value is dimensionless: clearance=0.04 offsets each gear by 0.04 * module, producing twice that normal separation between a mating pair of faces.

Alternatively, pass max_backlash_deg to specify the maximum conventional backlash: the total driven-gear rotation between contact on opposing flanks. For a noncircular pair the local driven pitch radius changes, so backlash also changes. ncgears chooses the face offset at the minimum driven pitch radius and reports both the requested maximum and the resulting minimum:

pair = ncgears.generate(
    "phi - 0.08*sin(2*phi)",
    max_backlash_deg=1.5,
)
print(pair.minimum_backlash_deg, pair.maximum_backlash_deg)

Conjugacy, protected-flank contact, and transmission error are verified before the intentional offset. The delivered outlines are then independently checked for validity, a single connected boundary, strict inward containment, retained tip thickness, and sampled assembled-pair interference. These stages and the resolved physical offset are recorded in metadata.json.

Start from a pitch curve

If the drive gear's pitch radius is easier to describe than its motion law, use a centrode expression:

pair = ncgears.generate_from_centrode(
    "1 + 0.08*cos(2*phi)",
    teeth=20,
    module=1.0,
    name="centrode_two_lobe",
)

The radius may use arbitrary units; ncgears scales its arc length to the requested tooth count and module. By default it solves the center distance for one mate revolution. A specific ratio can be selected with target_cycle_delta. For example, a five-lobed 5:2 angular ratio uses:

import math

pair = ncgears.generate_from_centrode(
    "1 + 0.08*cos(5*phi)",
    teeth=100,
    target_cycle_delta=5 * math.pi,
    name="five_to_two",
)

Every input uses the hybrid analytical involute engine. It evaluates the straight-rack flank and rounded rack-tip envelope equations without constructing or sweeping a complete rack solid, so remote rack material cannot erase a pitch-curve concavity. Exact addendum and dedendum offsets complete each tooth. An independent rolling pass uses each opposing gear as a cutter to remove measured root interference. Exact regular flank spans, addendum geometry, and the connected support cores are guarded. The eligible root region combines pitch-side material with analytic fillet/dedendum closures, so nonconvex cusp stock outside the pitch curve can be removed without reshaping a tooth tip. Finite open profiles clip each analytical curve in rolling-arc parameter space, then follow one quarter of the centrode back across the inner boundary. Source-domain padding is used only to solve endpoint teeth; it cannot change or clip the finished body.

Closed and open designs

Closed gears require a smooth, strictly increasing motion whose cycle advance produces an integer mate tooth count. A simple 2:1 pair is:

pair = ncgears.generate("2*phi", teeth=20)  # 20 drive teeth, 10 driven teeth

Finite, non-repeating motion can be generated as an open segment:

pair = ncgears.generate(
    "1.8*phi + 0.03*sin(phi)",
    open_=True,
    drive_end=2.4,
    teeth=12,
    name="finite_segment",
)

What is verified

The Python engine uses analytic generalized-involute branches for every gear, including finite open profiles and nonconvex centrodes. Shapely/GEOS nodes the exact flank, rack-tip fillet, addendum, and dedendum curves and arranges complete tooth bodies. Open bodies use an ordered, parameter-clipped analytical boundary rather than a radial sector intersection. A successful result includes checks for:

  • one precision-stable connected closed outline per gear, with hub-connected bodies
  • sampled whole-cycle solid interference
  • contact motion recovered from the finished outlines
  • analytic envelope/tangency, intersection, join, and chord residuals
  • cusp-free, exposed protected flanks with sampled conjugate contact coverage
  • iterative opposing-gear undercut generation confined to analytic root regions
  • root radius, tip thickness, and centrode curvature
  • drive-outline fidelity to the requested centrode
  • sliding-velocity and undercut diagnostics

metadata.json reports generation_backend: "hybrid_analytic_involute", flank sample count, maximum envelope residual, maximum envelope-tangency residual, chord error, protected flank diagnostics, outline-connectivity status, and iterative rolling-cut diagnostics. Pair verification uses a bounded thread pool of at most eight workers.

These geometry checks are not load-rating or manufacturing certification.

Development

python -m pip install -e ".[dev]"
python -m pytest
ruff check ncgears tests
python -m build

For magnified visual inspection of four representative roots on each gear:

python scripts/render_profile_zooms.py out/gear_pair

The GitHub Actions workflow tests Python 3.10–3.13, builds a platform-independent ncgears wheel, and smoke-tests the installed wheel. Shapely supplies its GEOS runtime through its own platform wheels.

Method and prior work

The pitch-curve equations follow Uwe Bäsel, "Determining the geometry of noncircular gears for given transmission function". Tooth geometry is constructed by evaluating its analytic straight-rack envelope. GEOS performs curve arrangement and solid regularization rather than project-specific intersection code. The silhouette-fitting problem addressed by Xu et al., "Computational Design and Optimization of Non-Circular Gears", is complementary: a fitted transmission derivative or polar centrode can be passed into ncgears.

Contributions and reproducible test cases are welcome through the issue tracker.

Project context

This project contains entirely AI generated code. This project has been my personal benchmark for determining how capable coding models are for over a year. Models have saturated this benchmark, so I'm releasing the project as an alpha.

License

ncgears is distributed under the Apache License 2.0.

About

Non-circular gear generator

Resources

Stars

Watchers

Forks

Releases

Contributors

Languages