Skip to content

Latest commit

 

History

History
587 lines (457 loc) · 26.1 KB

File metadata and controls

587 lines (457 loc) · 26.1 KB

Implementation description

This document describes the current ncgears implementation: how a requested motion becomes two pitch curves, how teeth are constructed on those curves, how non-working root interference is removed, and what is verified before an outline is returned. It also records the physical and numerical boundaries of that implementation.

ncgears has one tooth-geometry engine. All inputs ultimately pass through the same hybrid analytical generalized-involute pipeline. The distinction between a transmission-law input and a centrode input exists only at the front of the pipeline; both become the same sampled motion representation before geometry is constructed.

System structure

The implementation is divided into a few deliberately narrow layers:

  • ncgears/api.py parses expressions, differentiates them with SymPy, constructs closed or padded-open sample tables, and writes the source CSV.
  • ncgears/engine.py converts those samples into pitch geometry, constructs and arranges the analytical tooth curves, removes cutter interference, and runs verification.
  • ncgears/_policy.py contains sampling densities, tolerances, topology limits, and public defaults. Dimensional tolerances in this file are factors of module.
  • ncgears/result.py loads the generated outlines and metadata and provides SVG and DXF export.
  • ncgears/rendering.py provides optional previews and animation. Rendering is downstream of generation and does not alter the delivered geometry.

At a high level, generation follows this data flow:

flowchart TD
    A["Transmission expression or drive-centrode expression"] --> B["Validate, differentiate, and sample"]
    B --> C["Piecewise-quintic motion representation"]
    C --> D["Pitch radii, center distance, and common rolling arc"]
    D --> E1["Drive analytical tooth curves"]
    D --> E2["Driven analytical tooth curves"]
    E1 --> F["GEOS curve arrangement and initial solids"]
    E2 --> F
    F --> G["Opposing addendum-vertex undercut cuts"]
    G --> H["Conjugate-geometry and whole-solid verification"]
    H --> I["Optional global face clearance"]
    I --> J["Final connectivity and interference verification"]
    J --> K["Outline CSV and metadata JSON"]
Loading

The drive and driven analytical bodies are independent until the cutter and pair verification stages, so the engine constructs them concurrently when more than one worker is available. Phase verification also uses a bounded thread pool. The global worker limit is eight.

Input normalization

Transmission-law input

A transmission expression defines the driven angle psi as a function of drive angle phi:

psi = psi(phi)

The API subtracts the value at the active start, so the stored motion begins at zero without changing any derivative or geometry. SymPy evaluates psi and its first three derivatives on a uniform grid. The derivative must remain finite and strictly positive; the engine also rejects ratios outside its bounded numerical range.

In closed mode, the first three derivatives must agree at the period endpoints. The cycle advance is

Delta_psi = psi(phi_0 + period) - psi(phi_0),

and the mate tooth count is constrained by

Z_driven = Z_drive * period / Delta_psi.

That value must be integral. The closed sample count is rounded up to a multiple of the reduced tooth-ratio denominator so the sample grid and tooth cycles remain aligned. A second periodicity check is made after interpolation: shifting through one driven-body revolution must advance the motion by exactly one rigid driven revolution, with compatible first and second derivatives.

Drive-centrode input

A centrode expression defines an unscaled drive pitch radius r(phi). It must be positive and finite. Closed inputs must match in value, first derivative, and second derivative at the period endpoints.

The radius and an auxiliary reference center distance C_ref define a motion derivative:

psi1 = r / (C_ref - r)
psi2 = C_ref * r' / (C_ref - r)^2
psi3 = C_ref * (r'' / (C_ref - r)^2 + 2 * r'^2 / (C_ref - r)^3)

If C_ref is not supplied, the engine solves for it with a bracketed root search so that

integral(r / (C_ref - r), phi) = target_cycle_delta.

The solved derivative is numerically integrated to obtain psi. The original centrode units are only a shape and ratio reference. The common geometry stage later scales the resulting pitch length to the requested tooth count and module.

The common motion interpolant

Transmission CSV input contains phi, psi, psi1, psi2, and psi3. Geometry uses one uniform piecewise-quintic Hermite series constrained by psi, psi1, and psi2. Values and all evaluated derivatives through third order come from that series, keeping position, tangent, curvature, and curvature derivative consistent with one interpolant. The sampled psi3 column records the source evaluation but is not an independent constraint on the motion series.

Each quintic segment matches value, first derivative, and second derivative at both ends. Periodic series wrap the final segment to the first while adding the cycle advance. Non-periodic series clamp evaluation to their available sampled domain.

Open-input continuation

An open result needs additional motion history to construct teeth at the active endpoints. Padding lengths are specified in circular pitches and converted to angular spans using the local pitch-arc density. The user's expression is evaluated only on the requested active interval. Outside that interval the API synthesizes a piecewise-quintic continuation that matches endpoint value, tangent, and second derivative.

For a transmission law, the continuation settles to the endpoint angular ratio, which approaches a circular pitch curve. For a direct centrode, it settles to an approximately constant radius. The transition span is limited to avoid an unbounded radial excursion. Padding supplies construction history only: it does not define or clip the finished open body.

Pitch-curve construction

Let q = d psi / d phi and let C be the physical shaft center distance. For an external pair, the pitch radii are

r_drive(phi)  = C * q / (1 + q)
r_driven(phi) = C / (1 + q).

They sum to C at every pose. The drive-centrode arc density per unit center distance is

rho(phi) = hypot(psi2, q * (1 + q)) / (1 + q)^2.

With circular pitch p = pi * module, the center distance is selected so the active drive pitch length holds the requested number of teeth:

C = Z_drive * p / integral(rho(phi), phi).

The integral is represented by a dense cumulative Simpson table. It provides both arbitrary interval integrals and the inverse map from common rolling arc s back to phi. Closed lookups wrap by complete arc cycles; open lookups must remain inside the padded motion domain.

In the local complex coordinate systems used by the engine, the pitch points are

P_drive(phi)  =  r_drive(phi)  * exp(-i * (phi - phi_0))
P_driven(phi) = -r_driven(phi) * exp( i * (psi(phi) - psi(phi_0))).

The initial drive center is the origin. The driven outline is also generated about its own origin and is translated by C when assembled. Unit tangents are computed analytically from psi1 and psi2; oriented pitch-curve curvatures use derivatives through psi3.

The common rolling arc is the central parameter of tooth generation. A distance p in s is one tooth pitch on both members. This avoids placing teeth by polar angle, which would be wrong on a noncircular or nonconvex centrode.

Analytical tooth geometry

Straight-rack flank envelope

For tooth phase k, flank sign sigma in {-1, +1}, pressure angle alpha, pitch p, pitch point P(s), and pitch tangent T(s), define the rolling rack coordinate

lambda(s) = sigma * p / 4 - (s - k * p).

The generalized-involute working flank is evaluated directly as

X_flank(s) = P(s)
           + lambda(s) * T(s)
           * (cos(alpha) + i * sigma * sin(alpha)) * cos(alpha).

The member-specific pitch frame supplies the correct drive or driven orientation. This is the analytical envelope of a straight rack flank, not an approximation obtained by subtracting many sampled rack positions.

Addendum and dedendum curves are parallel offsets of the pitch curve:

X_offset(s, h) = P(s) + h * N(s),

where the outward unit normal N is selected for the member's orientation, h = addendum gives the tooth tip, and h = -dedendum gives the root boundary.

Rounded rack-tip fillet

The root fillet is another analytical envelope branch. The engine follows the center of the rack-tip circle at dedendum - fillet_radius, then offsets that center by the fillet radius along the normalized local envelope normal. The branch is selected continuously from exact dedendum contact, including across pitch-curve inflections. It is not a circular arc fitted to the finished polygon and not a post-processing blend.

The nominal flank-to-fillet contact and fillet-to-dedendum contact follow from the rack geometry. The addendum end of each flank is found by intersecting the continuous flank parameterization with the continuous addendum offset. GEOS intersects dense sampled curves to produce robust candidates; SciPy least-squares then refines the two curve parameters and measures the continuous residual. The same candidate-and-refinement pattern is used for nontrivial flank/fillet intersections.

Cusps and analytic undercut classification

A retained working flank must be regular. For the oriented pitch curvature kappa, a singular point satisfies the per-flank cusp equation

lambda * kappa - sigma * tan(alpha) = 0.

The engine searches the entire candidate working interval. It brackets sign changes and refines them with Brent's method. Because an even-multiplicity cusp does not change sign, sampled local minima of the absolute equation are also minimized and accepted when their residual is sufficiently small. The grid is repeatedly doubled until its root set stabilizes or reaches the policy limit.

If no cusp lies between the nominal rack-tip contact and the addendum, the analytic fillet is joined at its nominal tangent contact. If a cusp exists, the engine searches for a nontrivial regular intersection between the flank and the fillet and keeps the tip-side cusp-free component. If no such closure exists, it stops just beyond the cusp and inserts a sacrificial connection to close the initial stock. That case is a hybrid undercut: the connection is non-working material that the opposing gear's addendum-vertex trajectory must remove later.

Metadata distinguishes flanks classified as analytically undercut, hybrid cases, and the eventual root closure with analytic_undercut_count, hybrid_undercut_count, cutter_undercut_curve_count, and fillet_closure_mode.

Adaptive curve tessellation

Flank, fillet, addendum, dedendum, backing, and cutter paths all have continuous parameterizations. The engine samples them for intersection-candidate discovery, cusp and cutter-penetration searches, GEOS arrangement and Boolean operations, verification, and export. Candidate flank/offset and flank/fillet intersections are subsequently refined against the continuous parameterizations. Cutter stock penetration intervals remain point-sampled and are padded before subtraction.

For each interval, the engine compares the exact curve midpoint with its nearest point on the endpoint chord. It doubles the interval count until the maximum midpoint-to-chord error is within the module-scaled target or the sample ceiling is reached. Working flanks start with a denser minimum grid than closure curves. The ordinary analytical curve target is 0.000025 * module; finished cutter trajectories use the finer 0.0000025 * module target.

The delivered outline is therefore a tessellated polygon even though its source curves and intersection refinements are analytical.

Body assembly

Closed gears

A closed member begins with material inside the analytical dedendum offset, unioned with a small central support disk so the intended root body remains hub connected. Each tooth is then assembled in boundary order from:

  1. one rounded rack-tip fillet,
  2. one generalized-involute flank,
  3. the addendum offset between the two flank tips,
  4. the opposing generalized-involute flank,
  5. the opposing fillet, and
  6. the dedendum offset back to the first root.

GEOS validates and unions these tooth polygons with the root blank. Separate root-trim polygons form the intended cutter mask: the engine unions the pitch material with per-root closure regions, intersects that union with the retained body, and later adds a one-sided protected-flank guard. Working flanks and addendum material are therefore not removed merely because a cutter trajectory crosses them.

GEOS may return several polygonal pieces while regularizing a curve arrangement. The implementation retains the largest piece. Connected-loop checks apply to that retained outline, while the closed-drive centrode-fidelity and minimum-area checks and the subsequent pair checks catch broad losses of intended material. They do not prove that no smaller fragment was discarded during regularization.

Open gears

An open member is not made by building a padded closed solid and intersecting it with radial sector faces. Such an intersection is generally wrong for a noncircular pitch curve.

Instead, the engine walks one ordered boundary and clips every flank, fillet, addendum, and dedendum curve in common rolling-arc space to the active interval. Straight endpoint seams connect that outer boundary to an inner curve at one quarter of the centrode radius; the inner curve then returns from the active end to the active start. Open tooth phases are offset by one half pitch, centering the requested teeth between the active arc limits. Every constituent curve is still clipped to those limits, so the endpoint seams—not construction padding—complete the finite body.

Either member may span one complete body revolution. A span greater than one revolution is rejected because one open boundary could no longer represent it as a single non-self-overlapping body.

An open output is intended only for its finite active operating range. It must not be treated as a continuously rotating closed pair.

Cutter-trajectory root generation

No complete rack solid is swept through either gear. This is important for deep nonconvex centrodes: a remote part of a fictitious rack can pass through a concavity and erase valid material unrelated to the local tooth being cut.

The initial analytical body instead supplies exact working flanks and the preferred rounded root closures. Remaining interference is removed with the two vertices of every opposing addendum edge:

  1. Every opposing addendum vertex is transformed through the cutter search interval in each target gear's local frame: the complete cycle for a closed pair, or the active interval plus endpoint search padding for an open pair.
  2. A point-in-polygon search finds consecutive parameter intervals during which that vertex penetrates the initial target stock. A vertex that stays inside for an entire closed cycle is rejected as an invalid pair.
  3. Penetration depth is measured against the target boundary. Excursions no deeper than the ordinary analytical chord-error budget are treated as tessellation noise and ignored.
  4. Each significant interval is extended by one quarter of a circular pitch at both ends, limited by the available input domain.
  5. The continuous trajectory is adaptively tessellated, closed into a cutter region, and dilated by the requested root clearance plus a small Boolean allowance.
  6. The cut is intersected with both the initial solid and that member's analytic root-trim zone before subtraction.

For finite open profiles, the search covers one circular pitch beyond each requested endpoint using the construction padding already required for endpoint teeth. If a penetration interval reaches the finite search edge, a narrow local strip around the open trajectory closes the cut without reconstructing a complete cutter solid or requiring more user-defined motion.

Before final subtraction, the raw cut is used to discover which portion of every protected flank remains exposed and connected to its addendum tip. Only that tip-connected component remains a working flank. A one-sided guard is built on the material side of it and subtracted from the cutter region. This retains the flank up to its cutter intersection without leaving the doubled-back root sliver that a symmetric buffered-flank guard would create.

Cuts are unioned per member, subtracted, and precision-normalized to collapse near-coincident Boolean seams. The finished boundaries are then re-extracted and required to remain one precision-stable closed loop.

Clearance and backlash

Root clearance and global clearance occur at different stages and have different effects.

root_clearance expands only the addendum-vertex cutter regions before they are subtracted. It does not offset the working-flank faces. If an enlarged cut reaches the root-side end of a protected span, that span is shortened to its exposed tip-connected component; the remaining analytical component is guarded without being offset.

Global clearance is a per-face normal offset. After all zero-clearance conjugacy, protected-contact, and transmission-error checks pass, each complete solid is eroded inward with a constant-distance GEOS buffer. Re-entrant joins are rounded; convex corners remain intersections of their translated faces. The result must be one valid body, lie strictly inside the original, pass the rack-derived analytical tip-thickness guard, and remain interference-free over the sampled motion. The engine does not geometrically measure minimum tip thickness on the post-offset polygon.

If maximum driven-gear backlash beta_max is requested instead, the engine chooses the same per-face distance c at the minimum driven pitch radius:

c = beta_max * r_driven_min * cos(alpha) / 4
beta(phi) = 4 * c / (r_driven(phi) * cos(alpha)).

Angles in those equations are in radians. Metadata reports the resulting minimum and maximum total driven angular free play. Explicit global clearance and maximum backlash are mutually exclusive.

Verification model

Generation is fail-closed: a result is returned only after its analytical curves, polygon topology, protected working geometry, and assembled motion pass the implemented checks. Those checks combine continuous residual evaluation with dense sampled solid tests; they are not a formal proof over every real-valued phase.

Analytical and topological checks

The engine rejects a result when any enforced condition falls outside its tolerance. These conditions include:

  • straight-rack envelope and envelope-tangency residuals,
  • continuous curve-intersection residuals,
  • rack-tip-fillet contact with the dedendum,
  • adaptive midpoint-to-chord error,
  • cusp-free regularity of every retained working flank,
  • exposure of protected analytical flanks on the finished polygon boundary,
  • precision-noded single-loop connectivity,
  • positive rack-derived tooth-tip thickness after requested global clearance,
  • closed drive-outline fidelity to the requested centrode, and
  • a broad closed-body area check against the drive pitch area.

Other values are diagnostics rather than independent rejection criteria. The engine reports the minimum outline radius, sampled pitch-curve curvature, and a centrode-convexity classification without applying acceptance thresholds to them. Reported pre/post-clearance tip thickness is derived from the rack geometry and requested normal offset; it is not measured from the finished polygon.

The corresponding metadata includes:

  • maximum_envelope_residual
  • maximum_envelope_tangency_residual
  • maximum_intersection_residual
  • maximum_fillet_root_residual
  • maximum_analytic_chord_error
  • minimum_flank_regular_factor
  • maximum_protected_flank_boundary_error
  • maximum_protected_contact_residual

Whole-pair interference and contact

Whole-solid interference is evaluated at four staggered phase grids. Closed grids contain at least 64 base phases and at least four phases per tooth of the larger member; open grids contain at least 48 base phases. Offsets of zero, one half, one quarter, and three quarters of a grid cell reduce the chance that an error aligns with the primary phase grid. Polygon overlap area at every sampled pose must remain below the module-scaled GEOS allowance.

Protected analytical flank pairs are independently matched in common-arc space and transformed into the assembled pose. The engine reports the number of matching pairs, their maximum residual, and the fraction of sampled phases with at least one candidate. It rejects the pair if no sampled phase has a protected contact candidate, but it does not require candidate coverage at every phase; whole-solid contact recovery supplies the separate positive-contact check.

At several additional off-grid poses, selected with a non-dyadic phase offset, the engine searches for the first positive solid overlap on both sides of the requested driven angle. It expands the angular search and then bisects the first contact transition. The largest required correction is reported as maximum_transmission_error. This recovers contact from the finished tessellated solids rather than assuming that source-curve conjugacy alone guarantees contact after arrangement.

All contact and transmission-error measurements are made before intentional global clearance, because clearance deliberately separates the members at the nominal pose. After clearance, the engine repeats connectivity, containment, artifact, and sampled interference checks instead.

Surface sliding

Conjugacy and surface sliding are different quantities. For an external pair, the relative sliding speed at contact point Q is proportional to

(1 + psi1) * distance(Q, P),

where P is the instantaneous pitch point. A generalized involute pair therefore has zero sliding only as contact crosses the pitch point. Metadata reports a conservative sliding-velocity factor as well as the angular correction at which the tessellated finished solids establish contact.

Output artifacts

A successful generation writes the sampled source (transmission.csv or centrode.csv), counter-clockwise closed drive.csv and driven.csv outlines, and metadata.json. Each outline is expressed about its own shaft center; result and export code places the driven member at the reported center distance for pair views.

SVG export writes the delivered polygons directly. DXF export writes closed lightweight polylines and may simplify them with a separately specified module-scaled error. Neither export path participates in generation or verification. PNG, interactive Matplotlib, and GIF output are visualizations of the already generated pair.

Physical and numerical boundaries

What “general purpose” means

The program either returns a pair that passes its implemented solid checks or rejects the requested motion and design parameters with a specific error. It does not imply that every scalar function is physically realizable by one pair of fixed-center external gears.

A closed external pair requires:

  • a bounded, strictly positive transmission derivative,
  • a sufficiently smooth motion law,
  • rational cycle advance and integral drive/driven tooth counts,
  • motion history compatible with both rigid gear revolutions,
  • enough root material for a connected solid, and
  • positive contact without solid interference.

Exact dwells, infinite ratios, ratio reversals, discontinuous velocity, irrational closed ratios, and incompatible driven-cycle histories require an open segment or a different mechanism topology.

Floating point and sampling

Shapely/GEOS performs curve arrangement and Boolean operations in double precision. GEOS finds candidate intersections between sampled analytical curves, and SciPy refines them against the continuous parameterizations. Rounded rack-tip fillets are analytical envelope branches, not post-processing arcs.

All dimensional tolerances are factors of module defined in ncgears/_policy.py; there is no hidden unit-sized tolerance floor. Very large coordinate offsets, modules close to machine precision, or extremely thin remnants remain unsuitable inputs.

The four staggered verification grids and additional off-grid contact recovery catch many grid-aligned errors, but whole-solid verification remains dense sampling rather than formal interval arithmetic over every real-valued phase.

The two sampling controls affect different stages. samples sets the source expression grid and therefore the resolution of the piecewise-quintic motion interpolant. It should be increased when the motion law has high-frequency content or sharply changing derivatives. samples_per_radian sets the initial density of analytical-curve tessellation before adaptive chord-error refinement. Increasing samples_per_radian is appropriate when:

  • the tooth scale is very small relative to center distance,
  • high-frequency motion is already adequately resolved by samples but its resulting geometry needs a denser initial curve grid,
  • the reported contact correction is too large, or
  • manufacturing tolerance approaches the reported tessellation error.

Open-segment scope

Open bodies use exactly the same analytical flank, fillet, addendum, and dedendum curves as closed gears. Their finite boundary is clipped in rolling-arc space, not inferred from padding. The input expression only needs to be valid on the requested interval.

Construction padding, finite body closure, and endpoint cutter strips make an open segment geometrically self-contained, but they do not make it periodic. An open result is valid only over its requested active motion. Spans greater than one revolution of either body are unsupported.

Engineering analysis not included

The geometry report does not replace:

  • Hertzian contact-stress analysis,
  • tooth-root bending and fatigue analysis,
  • elastic transmission-error analysis,
  • lubrication and flash-temperature analysis,
  • three-dimensional lead/crowning design,
  • shaft, bearing, and housing deflection analysis, or
  • manufacturing-process validation.

Those require load, material, face width, speed, lubrication, and tolerance inputs outside the present two-dimensional geometry contract.