# Copyright (c) 2026, pinkfish
#
# Licensed under the BSD 2-Clause License. See the LICENSE file in the project
# root for the full license text.
# SPDX-License-Identifier: BSD-2-Clause
# LibFile: pybosl2/parts/ball_bearings.py
# Pure-Python port of BOSL2's ball_bearings.scad: models of standard ball-bearing cartridges.
# :meth:`BallBearings.ball_bearing` builds a bearing -- either a sealed/shielded cartridge (nested
# rings plus a shield face) or an open one (inner and outer races, a ball-race groove, and the
# balls) -- from a :class:`BearingType` trade size or explicit
# inner_diameter/outer_diameter/width.
# :meth:`BallBearings.ball_bearing_info` returns the tabulated dimensions as a :class:`BearingSpec`.
#
# The trade-size table is transcribed verbatim from ball_bearings.scad.
#
# FileSummary: Standard ball-bearing cartridge models.
# DocCategory: Parts library
# FileGroup: BOSL2
"""Standard ball-bearing cartridge models."""
from __future__ import annotations
import math
import operator
from dataclasses import dataclass
from enum import Enum, auto
from functools import reduce
from pybosl2.constants import INCH
from pybosl2.shapes3d import Bosl2Solid, sphere, torus, tube
__all__ = ["BallBearings", "BearingSpec", "BearingType"]
# string trade-name -> BearingType lookup, built from the enum names.
_BY_TRADE_NAME: dict[str, BearingType] = {}
class BearingType(Enum):
"""Trade-size identifier for standard ball-bearing cartridges.
Each member names a standard trade size (e.g. ``BEARING_608``, ``R8``, ``R8_ZZ``)
that :meth:`BallBearings.ball_bearing_info` and :meth:`BallBearings.ball_bearing`
accept. Use the enum to avoid typos and get IDE autocompletion for the available
sizes. String names (``"608"``, ``"R8ZZ"``) are also accepted via the
:func:`BearingType.of` helper.
"""
# R-series (inch)
R2 = auto()
R3 = auto()
R4 = auto()
R6 = auto()
R8 = auto()
R10 = auto()
R12 = auto()
R14 = auto()
R16 = auto()
R18 = auto()
R20 = auto()
R22 = auto()
R24 = auto()
# R-series shielded
R2_ZZ = auto()
R3_ZZ = auto()
R4_ZZ = auto()
R6_ZZ = auto()
R8_ZZ = auto()
R10_ZZ = auto()
R12_ZZ = auto()
R14_ZZ = auto()
R16_ZZ = auto()
R18_ZZ = auto()
R20_ZZ = auto()
R22_ZZ = auto()
R24_ZZ = auto()
# metric
BEARING_608 = auto()
BEARING_629 = auto()
BEARING_635 = auto()
BEARING_6000 = auto()
BEARING_6001 = auto()
BEARING_6002 = auto()
BEARING_6003 = auto()
BEARING_6007 = auto()
BEARING_6200 = auto()
BEARING_6201 = auto()
BEARING_6202 = auto()
BEARING_6203 = auto()
BEARING_6204 = auto()
BEARING_6205 = auto()
BEARING_6206 = auto()
BEARING_6207 = auto()
BEARING_6208 = auto()
BEARING_6209 = auto()
BEARING_6210 = auto()
BEARING_6211 = auto()
BEARING_6212 = auto()
BEARING_6301 = auto()
BEARING_6302 = auto()
BEARING_6303 = auto()
BEARING_6304 = auto()
BEARING_6305 = auto()
BEARING_6306 = auto()
BEARING_6307 = auto()
BEARING_6308 = auto()
BEARING_6309 = auto()
BEARING_6310 = auto()
BEARING_6311 = auto()
BEARING_6312 = auto()
BEARING_6403 = auto()
BEARING_6800 = auto()
BEARING_6801 = auto()
BEARING_6802 = auto()
BEARING_6803 = auto()
BEARING_6804 = auto()
BEARING_6805 = auto()
BEARING_6806 = auto()
BEARING_6900 = auto()
BEARING_6901 = auto()
BEARING_6902 = auto()
BEARING_6903 = auto()
BEARING_6904 = auto()
BEARING_6905 = auto()
BEARING_6906 = auto()
BEARING_6907 = auto()
BEARING_6908 = auto()
BEARING_16002 = auto()
BEARING_16004 = auto()
BEARING_16005 = auto()
BEARING_16100 = auto()
BEARING_16101 = auto()
# shielded metric
BEARING_608_ZZ = auto()
BEARING_629_ZZ = auto()
BEARING_635_ZZ = auto()
BEARING_6000_ZZ = auto()
BEARING_6001_ZZ = auto()
BEARING_6002_ZZ = auto()
BEARING_6003_ZZ = auto()
BEARING_6007_ZZ = auto()
BEARING_6200_ZZ = auto()
BEARING_6201_ZZ = auto()
BEARING_6202_ZZ = auto()
BEARING_6203_ZZ = auto()
BEARING_6204_ZZ = auto()
BEARING_6205_ZZ = auto()
BEARING_6206_ZZ = auto()
BEARING_6207_ZZ = auto()
BEARING_6208_ZZ = auto()
BEARING_6209_ZZ = auto()
BEARING_6210_ZZ = auto()
BEARING_6211_ZZ = auto()
BEARING_6212_ZZ = auto()
BEARING_6301_ZZ = auto()
BEARING_6302_ZZ = auto()
BEARING_6303_ZZ = auto()
BEARING_6304_ZZ = auto()
BEARING_6305_ZZ = auto()
BEARING_6306_ZZ = auto()
BEARING_6307_ZZ = auto()
BEARING_6308_ZZ = auto()
BEARING_6309_ZZ = auto()
BEARING_6310_ZZ = auto()
BEARING_6311_ZZ = auto()
BEARING_6312_ZZ = auto()
BEARING_6403_ZZ = auto()
BEARING_6800_ZZ = auto()
BEARING_6801_ZZ = auto()
BEARING_6802_ZZ = auto()
BEARING_6803_ZZ = auto()
BEARING_6804_ZZ = auto()
BEARING_6805_ZZ = auto()
BEARING_6806_ZZ = auto()
BEARING_6900_ZZ = auto()
BEARING_6901_ZZ = auto()
BEARING_6902_ZZ = auto()
BEARING_6903_ZZ = auto()
BEARING_6904_ZZ = auto()
BEARING_6905_ZZ = auto()
BEARING_6906_ZZ = auto()
BEARING_6907_ZZ = auto()
BEARING_6908_ZZ = auto()
BEARING_16002_ZZ = auto()
BEARING_16004_ZZ = auto()
BEARING_16005_ZZ = auto()
BEARING_16100_ZZ = auto()
BEARING_16101_ZZ = auto()
@classmethod
def of(cls, trade_name: str) -> BearingType:
"""Look up a :class:`BearingType` from its trade-name string (``"608"``, ``"R8ZZ"``)."""
bt = _BY_TRADE_NAME.get(trade_name)
if bt is not None:
return bt
raise ValueError(f"Unsupported ball bearing trade size: {trade_name!r}")
# Map trade-name strings to BearingType enum members.
# Derived from the enum member names: R8 -> "R8", BEARING_608 -> "608", BEARING_608_ZZ -> "608ZZ"
_BY_TRADE_NAME = {
"R2": BearingType.R2,
"R3": BearingType.R3,
"R4": BearingType.R4,
"R6": BearingType.R6,
"R8": BearingType.R8,
"R10": BearingType.R10,
"R12": BearingType.R12,
"R14": BearingType.R14,
"R16": BearingType.R16,
"R18": BearingType.R18,
"R20": BearingType.R20,
"R22": BearingType.R22,
"R24": BearingType.R24,
"R2ZZ": BearingType.R2_ZZ,
"R3ZZ": BearingType.R3_ZZ,
"R4ZZ": BearingType.R4_ZZ,
"R6ZZ": BearingType.R6_ZZ,
"R8ZZ": BearingType.R8_ZZ,
"R10ZZ": BearingType.R10_ZZ,
"R12ZZ": BearingType.R12_ZZ,
"R14ZZ": BearingType.R14_ZZ,
"R16ZZ": BearingType.R16_ZZ,
"R18ZZ": BearingType.R18_ZZ,
"R20ZZ": BearingType.R20_ZZ,
"R22ZZ": BearingType.R22_ZZ,
"R24ZZ": BearingType.R24_ZZ,
"608": BearingType.BEARING_608,
"629": BearingType.BEARING_629,
"635": BearingType.BEARING_635,
"6000": BearingType.BEARING_6000,
"6001": BearingType.BEARING_6001,
"6002": BearingType.BEARING_6002,
"6003": BearingType.BEARING_6003,
"6007": BearingType.BEARING_6007,
"6200": BearingType.BEARING_6200,
"6201": BearingType.BEARING_6201,
"6202": BearingType.BEARING_6202,
"6203": BearingType.BEARING_6203,
"6204": BearingType.BEARING_6204,
"6205": BearingType.BEARING_6205,
"6206": BearingType.BEARING_6206,
"6207": BearingType.BEARING_6207,
"6208": BearingType.BEARING_6208,
"6209": BearingType.BEARING_6209,
"6210": BearingType.BEARING_6210,
"6211": BearingType.BEARING_6211,
"6212": BearingType.BEARING_6212,
"6301": BearingType.BEARING_6301,
"6302": BearingType.BEARING_6302,
"6303": BearingType.BEARING_6303,
"6304": BearingType.BEARING_6304,
"6305": BearingType.BEARING_6305,
"6306": BearingType.BEARING_6306,
"6307": BearingType.BEARING_6307,
"6308": BearingType.BEARING_6308,
"6309": BearingType.BEARING_6309,
"6310": BearingType.BEARING_6310,
"6311": BearingType.BEARING_6311,
"6312": BearingType.BEARING_6312,
"6403": BearingType.BEARING_6403,
"6800": BearingType.BEARING_6800,
"6801": BearingType.BEARING_6801,
"6802": BearingType.BEARING_6802,
"6803": BearingType.BEARING_6803,
"6804": BearingType.BEARING_6804,
"6805": BearingType.BEARING_6805,
"6806": BearingType.BEARING_6806,
"6900": BearingType.BEARING_6900,
"6901": BearingType.BEARING_6901,
"6902": BearingType.BEARING_6902,
"6903": BearingType.BEARING_6903,
"6904": BearingType.BEARING_6904,
"6905": BearingType.BEARING_6905,
"6906": BearingType.BEARING_6906,
"6907": BearingType.BEARING_6907,
"6908": BearingType.BEARING_6908,
"16002": BearingType.BEARING_16002,
"16004": BearingType.BEARING_16004,
"16005": BearingType.BEARING_16005,
"16100": BearingType.BEARING_16100,
"16101": BearingType.BEARING_16101,
"608ZZ": BearingType.BEARING_608_ZZ,
"629ZZ": BearingType.BEARING_629_ZZ,
"635ZZ": BearingType.BEARING_635_ZZ,
"6000ZZ": BearingType.BEARING_6000_ZZ,
"6001ZZ": BearingType.BEARING_6001_ZZ,
"6002ZZ": BearingType.BEARING_6002_ZZ,
"6003ZZ": BearingType.BEARING_6003_ZZ,
"6007ZZ": BearingType.BEARING_6007_ZZ,
"6200ZZ": BearingType.BEARING_6200_ZZ,
"6201ZZ": BearingType.BEARING_6201_ZZ,
"6202ZZ": BearingType.BEARING_6202_ZZ,
"6203ZZ": BearingType.BEARING_6203_ZZ,
"6204ZZ": BearingType.BEARING_6204_ZZ,
"6205ZZ": BearingType.BEARING_6205_ZZ,
"6206ZZ": BearingType.BEARING_6206_ZZ,
"6207ZZ": BearingType.BEARING_6207_ZZ,
"6208ZZ": BearingType.BEARING_6208_ZZ,
"6209ZZ": BearingType.BEARING_6209_ZZ,
"6210ZZ": BearingType.BEARING_6210_ZZ,
"6211ZZ": BearingType.BEARING_6211_ZZ,
"6212ZZ": BearingType.BEARING_6212_ZZ,
"6301ZZ": BearingType.BEARING_6301_ZZ,
"6302ZZ": BearingType.BEARING_6302_ZZ,
"6303ZZ": BearingType.BEARING_6303_ZZ,
"6304ZZ": BearingType.BEARING_6304_ZZ,
"6305ZZ": BearingType.BEARING_6305_ZZ,
"6306ZZ": BearingType.BEARING_6306_ZZ,
"6307ZZ": BearingType.BEARING_6307_ZZ,
"6308ZZ": BearingType.BEARING_6308_ZZ,
"6309ZZ": BearingType.BEARING_6309_ZZ,
"6310ZZ": BearingType.BEARING_6310_ZZ,
"6311ZZ": BearingType.BEARING_6311_ZZ,
"6312ZZ": BearingType.BEARING_6312_ZZ,
"6403ZZ": BearingType.BEARING_6403_ZZ,
"6800ZZ": BearingType.BEARING_6800_ZZ,
"6801ZZ": BearingType.BEARING_6801_ZZ,
"6802ZZ": BearingType.BEARING_6802_ZZ,
"6803ZZ": BearingType.BEARING_6803_ZZ,
"6804ZZ": BearingType.BEARING_6804_ZZ,
"6805ZZ": BearingType.BEARING_6805_ZZ,
"6806ZZ": BearingType.BEARING_6806_ZZ,
"6900ZZ": BearingType.BEARING_6900_ZZ,
"6901ZZ": BearingType.BEARING_6901_ZZ,
"6902ZZ": BearingType.BEARING_6902_ZZ,
"6903ZZ": BearingType.BEARING_6903_ZZ,
"6904ZZ": BearingType.BEARING_6904_ZZ,
"6905ZZ": BearingType.BEARING_6905_ZZ,
"6906ZZ": BearingType.BEARING_6906_ZZ,
"6907ZZ": BearingType.BEARING_6907_ZZ,
"6908ZZ": BearingType.BEARING_6908_ZZ,
"16002ZZ": BearingType.BEARING_16002_ZZ,
"16004ZZ": BearingType.BEARING_16004_ZZ,
"16005ZZ": BearingType.BEARING_16005_ZZ,
"16100ZZ": BearingType.BEARING_16100_ZZ,
"16101ZZ": BearingType.BEARING_16101_ZZ,
}
[docs]
@dataclass(frozen=True)
class BearingSpec:
"""Tabulated dimensions of a standard ball-bearing cartridge.
Returned by :meth:`BallBearings.ball_bearing_info` when looking up a
:class:`BearingType` trade size.
"""
inner_diameter: float # inner (shaft) diameter
outer_diameter: float # outer diameter
width: float # axial width
shielded: bool # True for a sealed/shielded (ZZ) cartridge
_I = INCH
# BearingType -> BearingSpec, transcribed from ball_bearings.scad.
_BEARINGS: dict[BearingType, BearingSpec] = {
BearingType.R2: BearingSpec(1 / 8 * _I, 3 / 8 * _I, 5 / 32 * _I, False),
BearingType.R3: BearingSpec(3 / 16 * _I, 1 / 2 * _I, 5 / 32 * _I, False),
BearingType.R4: BearingSpec(1 / 4 * _I, 5 / 8 * _I, 0.196 * _I, False),
BearingType.R6: BearingSpec(3 / 8 * _I, 7 / 8 * _I, 7 / 32 * _I, False),
BearingType.R8: BearingSpec(1 / 2 * _I, 9 / 8 * _I, 1 / 4 * _I, False),
BearingType.R10: BearingSpec(5 / 8 * _I, 11 / 8 * _I, 9 / 32 * _I, False),
BearingType.R12: BearingSpec(3 / 4 * _I, 13 / 8 * _I, 5 / 16 * _I, False),
BearingType.R14: BearingSpec(7 / 8 * _I, 15 / 8 * _I, 3 / 8 * _I, False),
BearingType.R16: BearingSpec(8 / 8 * _I, 16 / 8 * _I, 3 / 8 * _I, False),
BearingType.R18: BearingSpec(9 / 8 * _I, 17 / 8 * _I, 3 / 8 * _I, False),
BearingType.R20: BearingSpec(10 / 8 * _I, 18 / 8 * _I, 3 / 8 * _I, False),
BearingType.R22: BearingSpec(11 / 8 * _I, 20 / 8 * _I, 7 / 16 * _I, False),
BearingType.R24: BearingSpec(12 / 8 * _I, 21 / 8 * _I, 7 / 16 * _I, False),
BearingType.BEARING_608: BearingSpec(8, 22, 7, False),
BearingType.BEARING_629: BearingSpec(9, 26, 8, False),
BearingType.BEARING_635: BearingSpec(5, 19, 6, False),
BearingType.BEARING_6000: BearingSpec(10, 26, 8, False),
BearingType.BEARING_6001: BearingSpec(12, 28, 8, False),
BearingType.BEARING_6002: BearingSpec(15, 32, 9, False),
BearingType.BEARING_6003: BearingSpec(17, 35, 10, False),
BearingType.BEARING_6007: BearingSpec(35, 62, 14, False),
BearingType.BEARING_6200: BearingSpec(10, 30, 9, False),
BearingType.BEARING_6201: BearingSpec(12, 32, 10, False),
BearingType.BEARING_6202: BearingSpec(15, 35, 11, False),
BearingType.BEARING_6203: BearingSpec(17, 40, 12, False),
BearingType.BEARING_6204: BearingSpec(20, 47, 14, False),
BearingType.BEARING_6205: BearingSpec(25, 52, 15, False),
BearingType.BEARING_6206: BearingSpec(30, 62, 16, False),
BearingType.BEARING_6207: BearingSpec(35, 72, 17, False),
BearingType.BEARING_6208: BearingSpec(40, 80, 18, False),
BearingType.BEARING_6209: BearingSpec(45, 85, 19, False),
BearingType.BEARING_6210: BearingSpec(50, 90, 20, False),
BearingType.BEARING_6211: BearingSpec(55, 100, 21, False),
BearingType.BEARING_6212: BearingSpec(60, 110, 22, False),
BearingType.BEARING_6301: BearingSpec(12, 37, 12, False),
BearingType.BEARING_6302: BearingSpec(15, 42, 13, False),
BearingType.BEARING_6303: BearingSpec(17, 47, 14, False),
BearingType.BEARING_6304: BearingSpec(20, 52, 15, False),
BearingType.BEARING_6305: BearingSpec(25, 62, 17, False),
BearingType.BEARING_6306: BearingSpec(30, 72, 19, False),
BearingType.BEARING_6307: BearingSpec(35, 80, 21, False),
BearingType.BEARING_6308: BearingSpec(40, 90, 23, False),
BearingType.BEARING_6309: BearingSpec(45, 100, 25, False),
BearingType.BEARING_6310: BearingSpec(50, 110, 27, False),
BearingType.BEARING_6311: BearingSpec(55, 120, 29, False),
BearingType.BEARING_6312: BearingSpec(60, 130, 31, False),
BearingType.BEARING_6403: BearingSpec(17, 62, 17, False),
BearingType.BEARING_6800: BearingSpec(10, 19, 5, False),
BearingType.BEARING_6801: BearingSpec(12, 21, 5, False),
BearingType.BEARING_6802: BearingSpec(15, 24, 5, False),
BearingType.BEARING_6803: BearingSpec(17, 26, 5, False),
BearingType.BEARING_6804: BearingSpec(20, 32, 7, False),
BearingType.BEARING_6805: BearingSpec(25, 37, 7, False),
BearingType.BEARING_6806: BearingSpec(30, 42, 7, False),
BearingType.BEARING_6900: BearingSpec(10, 22, 6, False),
BearingType.BEARING_6901: BearingSpec(12, 24, 6, False),
BearingType.BEARING_6902: BearingSpec(15, 28, 7, False),
BearingType.BEARING_6903: BearingSpec(17, 30, 7, False),
BearingType.BEARING_6904: BearingSpec(20, 37, 9, False),
BearingType.BEARING_6905: BearingSpec(25, 42, 9, False),
BearingType.BEARING_6906: BearingSpec(30, 47, 9, False),
BearingType.BEARING_6907: BearingSpec(35, 55, 10, False),
BearingType.BEARING_6908: BearingSpec(40, 62, 12, False),
BearingType.BEARING_16002: BearingSpec(15, 22, 8, False),
BearingType.BEARING_16004: BearingSpec(20, 42, 8, False),
BearingType.BEARING_16005: BearingSpec(25, 47, 8, False),
BearingType.BEARING_16100: BearingSpec(10, 28, 8, False),
BearingType.BEARING_16101: BearingSpec(12, 30, 8, False),
}
# Add the "...ZZ" shielded variants, sharing the open variant's dimensions.
_ZZ_BEARINGS = {
BearingType.R2_ZZ: BearingSpec(
_BEARINGS[BearingType.R2].inner_diameter,
_BEARINGS[BearingType.R2].outer_diameter,
_BEARINGS[BearingType.R2].width,
True,
),
BearingType.R3_ZZ: BearingSpec(
_BEARINGS[BearingType.R3].inner_diameter,
_BEARINGS[BearingType.R3].outer_diameter,
_BEARINGS[BearingType.R3].width,
True,
),
BearingType.R4_ZZ: BearingSpec(
_BEARINGS[BearingType.R4].inner_diameter,
_BEARINGS[BearingType.R4].outer_diameter,
_BEARINGS[BearingType.R4].width,
True,
),
BearingType.R6_ZZ: BearingSpec(
_BEARINGS[BearingType.R6].inner_diameter,
_BEARINGS[BearingType.R6].outer_diameter,
_BEARINGS[BearingType.R6].width,
True,
),
BearingType.R8_ZZ: BearingSpec(
_BEARINGS[BearingType.R8].inner_diameter,
_BEARINGS[BearingType.R8].outer_diameter,
_BEARINGS[BearingType.R8].width,
True,
),
BearingType.R10_ZZ: BearingSpec(
_BEARINGS[BearingType.R10].inner_diameter,
_BEARINGS[BearingType.R10].outer_diameter,
_BEARINGS[BearingType.R10].width,
True,
),
BearingType.R12_ZZ: BearingSpec(
_BEARINGS[BearingType.R12].inner_diameter,
_BEARINGS[BearingType.R12].outer_diameter,
_BEARINGS[BearingType.R12].width,
True,
),
BearingType.R14_ZZ: BearingSpec(
_BEARINGS[BearingType.R14].inner_diameter,
_BEARINGS[BearingType.R14].outer_diameter,
_BEARINGS[BearingType.R14].width,
True,
),
BearingType.R16_ZZ: BearingSpec(
_BEARINGS[BearingType.R16].inner_diameter,
_BEARINGS[BearingType.R16].outer_diameter,
_BEARINGS[BearingType.R16].width,
True,
),
BearingType.R18_ZZ: BearingSpec(
_BEARINGS[BearingType.R18].inner_diameter,
_BEARINGS[BearingType.R18].outer_diameter,
_BEARINGS[BearingType.R18].width,
True,
),
BearingType.R20_ZZ: BearingSpec(
_BEARINGS[BearingType.R20].inner_diameter,
_BEARINGS[BearingType.R20].outer_diameter,
_BEARINGS[BearingType.R20].width,
True,
),
BearingType.R22_ZZ: BearingSpec(
_BEARINGS[BearingType.R22].inner_diameter,
_BEARINGS[BearingType.R22].outer_diameter,
_BEARINGS[BearingType.R22].width,
True,
),
BearingType.R24_ZZ: BearingSpec(
_BEARINGS[BearingType.R24].inner_diameter,
_BEARINGS[BearingType.R24].outer_diameter,
_BEARINGS[BearingType.R24].width,
True,
),
BearingType.BEARING_608_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_608].inner_diameter,
_BEARINGS[BearingType.BEARING_608].outer_diameter,
_BEARINGS[BearingType.BEARING_608].width,
True,
),
BearingType.BEARING_629_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_629].inner_diameter,
_BEARINGS[BearingType.BEARING_629].outer_diameter,
_BEARINGS[BearingType.BEARING_629].width,
True,
),
BearingType.BEARING_635_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_635].inner_diameter,
_BEARINGS[BearingType.BEARING_635].outer_diameter,
_BEARINGS[BearingType.BEARING_635].width,
True,
),
BearingType.BEARING_6000_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6000].inner_diameter,
_BEARINGS[BearingType.BEARING_6000].outer_diameter,
_BEARINGS[BearingType.BEARING_6000].width,
True,
),
BearingType.BEARING_6001_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6001].inner_diameter,
_BEARINGS[BearingType.BEARING_6001].outer_diameter,
_BEARINGS[BearingType.BEARING_6001].width,
True,
),
BearingType.BEARING_6002_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6002].inner_diameter,
_BEARINGS[BearingType.BEARING_6002].outer_diameter,
_BEARINGS[BearingType.BEARING_6002].width,
True,
),
BearingType.BEARING_6003_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6003].inner_diameter,
_BEARINGS[BearingType.BEARING_6003].outer_diameter,
_BEARINGS[BearingType.BEARING_6003].width,
True,
),
BearingType.BEARING_6007_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6007].inner_diameter,
_BEARINGS[BearingType.BEARING_6007].outer_diameter,
_BEARINGS[BearingType.BEARING_6007].width,
True,
),
BearingType.BEARING_6200_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6200].inner_diameter,
_BEARINGS[BearingType.BEARING_6200].outer_diameter,
_BEARINGS[BearingType.BEARING_6200].width,
True,
),
BearingType.BEARING_6201_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6201].inner_diameter,
_BEARINGS[BearingType.BEARING_6201].outer_diameter,
_BEARINGS[BearingType.BEARING_6201].width,
True,
),
BearingType.BEARING_6202_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6202].inner_diameter,
_BEARINGS[BearingType.BEARING_6202].outer_diameter,
_BEARINGS[BearingType.BEARING_6202].width,
True,
),
BearingType.BEARING_6203_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6203].inner_diameter,
_BEARINGS[BearingType.BEARING_6203].outer_diameter,
_BEARINGS[BearingType.BEARING_6203].width,
True,
),
BearingType.BEARING_6204_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6204].inner_diameter,
_BEARINGS[BearingType.BEARING_6204].outer_diameter,
_BEARINGS[BearingType.BEARING_6204].width,
True,
),
BearingType.BEARING_6205_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6205].inner_diameter,
_BEARINGS[BearingType.BEARING_6205].outer_diameter,
_BEARINGS[BearingType.BEARING_6205].width,
True,
),
BearingType.BEARING_6206_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6206].inner_diameter,
_BEARINGS[BearingType.BEARING_6206].outer_diameter,
_BEARINGS[BearingType.BEARING_6206].width,
True,
),
BearingType.BEARING_6207_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6207].inner_diameter,
_BEARINGS[BearingType.BEARING_6207].outer_diameter,
_BEARINGS[BearingType.BEARING_6207].width,
True,
),
BearingType.BEARING_6208_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6208].inner_diameter,
_BEARINGS[BearingType.BEARING_6208].outer_diameter,
_BEARINGS[BearingType.BEARING_6208].width,
True,
),
BearingType.BEARING_6209_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6209].inner_diameter,
_BEARINGS[BearingType.BEARING_6209].outer_diameter,
_BEARINGS[BearingType.BEARING_6209].width,
True,
),
BearingType.BEARING_6210_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6210].inner_diameter,
_BEARINGS[BearingType.BEARING_6210].outer_diameter,
_BEARINGS[BearingType.BEARING_6210].width,
True,
),
BearingType.BEARING_6211_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6211].inner_diameter,
_BEARINGS[BearingType.BEARING_6211].outer_diameter,
_BEARINGS[BearingType.BEARING_6211].width,
True,
),
BearingType.BEARING_6212_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6212].inner_diameter,
_BEARINGS[BearingType.BEARING_6212].outer_diameter,
_BEARINGS[BearingType.BEARING_6212].width,
True,
),
BearingType.BEARING_6301_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6301].inner_diameter,
_BEARINGS[BearingType.BEARING_6301].outer_diameter,
_BEARINGS[BearingType.BEARING_6301].width,
True,
),
BearingType.BEARING_6302_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6302].inner_diameter,
_BEARINGS[BearingType.BEARING_6302].outer_diameter,
_BEARINGS[BearingType.BEARING_6302].width,
True,
),
BearingType.BEARING_6303_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6303].inner_diameter,
_BEARINGS[BearingType.BEARING_6303].outer_diameter,
_BEARINGS[BearingType.BEARING_6303].width,
True,
),
BearingType.BEARING_6304_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6304].inner_diameter,
_BEARINGS[BearingType.BEARING_6304].outer_diameter,
_BEARINGS[BearingType.BEARING_6304].width,
True,
),
BearingType.BEARING_6305_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6305].inner_diameter,
_BEARINGS[BearingType.BEARING_6305].outer_diameter,
_BEARINGS[BearingType.BEARING_6305].width,
True,
),
BearingType.BEARING_6306_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6306].inner_diameter,
_BEARINGS[BearingType.BEARING_6306].outer_diameter,
_BEARINGS[BearingType.BEARING_6306].width,
True,
),
BearingType.BEARING_6307_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6307].inner_diameter,
_BEARINGS[BearingType.BEARING_6307].outer_diameter,
_BEARINGS[BearingType.BEARING_6307].width,
True,
),
BearingType.BEARING_6308_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6308].inner_diameter,
_BEARINGS[BearingType.BEARING_6308].outer_diameter,
_BEARINGS[BearingType.BEARING_6308].width,
True,
),
BearingType.BEARING_6309_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6309].inner_diameter,
_BEARINGS[BearingType.BEARING_6309].outer_diameter,
_BEARINGS[BearingType.BEARING_6309].width,
True,
),
BearingType.BEARING_6310_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6310].inner_diameter,
_BEARINGS[BearingType.BEARING_6310].outer_diameter,
_BEARINGS[BearingType.BEARING_6310].width,
True,
),
BearingType.BEARING_6311_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6311].inner_diameter,
_BEARINGS[BearingType.BEARING_6311].outer_diameter,
_BEARINGS[BearingType.BEARING_6311].width,
True,
),
BearingType.BEARING_6312_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6312].inner_diameter,
_BEARINGS[BearingType.BEARING_6312].outer_diameter,
_BEARINGS[BearingType.BEARING_6312].width,
True,
),
BearingType.BEARING_6403_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6403].inner_diameter,
_BEARINGS[BearingType.BEARING_6403].outer_diameter,
_BEARINGS[BearingType.BEARING_6403].width,
True,
),
BearingType.BEARING_6800_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6800].inner_diameter,
_BEARINGS[BearingType.BEARING_6800].outer_diameter,
_BEARINGS[BearingType.BEARING_6800].width,
True,
),
BearingType.BEARING_6801_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6801].inner_diameter,
_BEARINGS[BearingType.BEARING_6801].outer_diameter,
_BEARINGS[BearingType.BEARING_6801].width,
True,
),
BearingType.BEARING_6802_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6802].inner_diameter,
_BEARINGS[BearingType.BEARING_6802].outer_diameter,
_BEARINGS[BearingType.BEARING_6802].width,
True,
),
BearingType.BEARING_6803_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6803].inner_diameter,
_BEARINGS[BearingType.BEARING_6803].outer_diameter,
_BEARINGS[BearingType.BEARING_6803].width,
True,
),
BearingType.BEARING_6804_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6804].inner_diameter,
_BEARINGS[BearingType.BEARING_6804].outer_diameter,
_BEARINGS[BearingType.BEARING_6804].width,
True,
),
BearingType.BEARING_6805_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6805].inner_diameter,
_BEARINGS[BearingType.BEARING_6805].outer_diameter,
_BEARINGS[BearingType.BEARING_6805].width,
True,
),
BearingType.BEARING_6806_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6806].inner_diameter,
_BEARINGS[BearingType.BEARING_6806].outer_diameter,
_BEARINGS[BearingType.BEARING_6806].width,
True,
),
BearingType.BEARING_6900_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6900].inner_diameter,
_BEARINGS[BearingType.BEARING_6900].outer_diameter,
_BEARINGS[BearingType.BEARING_6900].width,
True,
),
BearingType.BEARING_6901_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6901].inner_diameter,
_BEARINGS[BearingType.BEARING_6901].outer_diameter,
_BEARINGS[BearingType.BEARING_6901].width,
True,
),
BearingType.BEARING_6902_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6902].inner_diameter,
_BEARINGS[BearingType.BEARING_6902].outer_diameter,
_BEARINGS[BearingType.BEARING_6902].width,
True,
),
BearingType.BEARING_6903_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6903].inner_diameter,
_BEARINGS[BearingType.BEARING_6903].outer_diameter,
_BEARINGS[BearingType.BEARING_6903].width,
True,
),
BearingType.BEARING_6904_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6904].inner_diameter,
_BEARINGS[BearingType.BEARING_6904].outer_diameter,
_BEARINGS[BearingType.BEARING_6904].width,
True,
),
BearingType.BEARING_6905_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6905].inner_diameter,
_BEARINGS[BearingType.BEARING_6905].outer_diameter,
_BEARINGS[BearingType.BEARING_6905].width,
True,
),
BearingType.BEARING_6906_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6906].inner_diameter,
_BEARINGS[BearingType.BEARING_6906].outer_diameter,
_BEARINGS[BearingType.BEARING_6906].width,
True,
),
BearingType.BEARING_6907_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6907].inner_diameter,
_BEARINGS[BearingType.BEARING_6907].outer_diameter,
_BEARINGS[BearingType.BEARING_6907].width,
True,
),
BearingType.BEARING_6908_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_6908].inner_diameter,
_BEARINGS[BearingType.BEARING_6908].outer_diameter,
_BEARINGS[BearingType.BEARING_6908].width,
True,
),
BearingType.BEARING_16002_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_16002].inner_diameter,
_BEARINGS[BearingType.BEARING_16002].outer_diameter,
_BEARINGS[BearingType.BEARING_16002].width,
True,
),
BearingType.BEARING_16004_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_16004].inner_diameter,
_BEARINGS[BearingType.BEARING_16004].outer_diameter,
_BEARINGS[BearingType.BEARING_16004].width,
True,
),
BearingType.BEARING_16005_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_16005].inner_diameter,
_BEARINGS[BearingType.BEARING_16005].outer_diameter,
_BEARINGS[BearingType.BEARING_16005].width,
True,
),
BearingType.BEARING_16100_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_16100].inner_diameter,
_BEARINGS[BearingType.BEARING_16100].outer_diameter,
_BEARINGS[BearingType.BEARING_16100].width,
True,
),
BearingType.BEARING_16101_ZZ: BearingSpec(
_BEARINGS[BearingType.BEARING_16101].inner_diameter,
_BEARINGS[BearingType.BEARING_16101].outer_diameter,
_BEARINGS[BearingType.BEARING_16101].width,
True,
),
}
_BEARINGS.update(_ZZ_BEARINGS)
[docs]
class BallBearings:
"""Models of standard ball-bearing cartridges.
Port of BOSL2's ``ball_bearings.scad``. Builds sealed/shielded or open bearings
from a trade size or explicit dimensions.
.. seealso::
`Visual spec sheet <specs/ball_bearings.html>`_ — measurements and STL previews
"""
[docs]
@staticmethod
def ball_bearing_info(trade_size: str | BearingType) -> BearingSpec:
"""Look up the tabulated dimensions for a trade-size bearing.
Accepts a string name (``"608"``, ``"6902ZZ"``) or a :class:`BearingType` enum value,
and returns the corresponding :class:`BearingSpec`.
Args:
trade_size: The bearing trade size as a string (e.g. ``"608"`` or ``"R8ZZ"``)
or a :class:`BearingType` enum value.
Returns:
A :class:`BearingSpec` with the inner_diameter, outer_diameter, width, and shielded flag.
Raises:
ValueError: If the trade size is not found in the bearing table.
"""
if isinstance(trade_size, str):
trade_size = BearingType.of(trade_size)
try:
return _BEARINGS[trade_size]
except KeyError:
raise ValueError(f"Unsupported ball bearing trade size: {trade_size!r}") from None
[docs]
@staticmethod
def ball_bearing(
trade_size: str | BearingType | None = None,
inner_diameter: float | None = None,
outer_diameter: float | None = None,
width: float | None = None,
shield: bool = True,
color: str | None = "silver",
fn: int | None = None,
fa: float | None = None,
fs: float | None = None,
) -> Bosl2Solid:
"""Build a standard ball-bearing cartridge model.
Give a *trade_size* name (or :class:`BearingType`), or explicit
*inner_diameter*/*outer_diameter*/*width* (with *shield*). Returns a
:class:`~pybosl2.shapes3d.Bosl2Solid` centered on the origin.
Args:
trade_size: The bearing trade size as a string or :class:`BearingType`.
Overrides explicit dimensions if given.
inner_diameter: Inner (shaft) diameter in mm. Required if trade_size is not given.
outer_diameter: Outer diameter in mm. Required if trade_size is not given.
width: Axial width in mm. Required if trade_size is not given.
shield: Model sealed/shielded cartridge (True) or open bearing with balls (False). Defaults to True.
color: Color name to apply to the bearing model. Defaults to "silver".
fn: Number of fragments for cylinder resolution. Passed to the geometry primitives.
fa: Minimum fragment angle. Passed to the geometry primitives.
fs: Minimum fragment size. Passed to the geometry primitives.
Returns:
A ball-bearing cartridge as a :class:`~pybosl2.shapes3d.Bosl2Solid`.
Raises:
ValueError: If inner_diameter, outer_diameter, or width are not provided and trade_size is not given.
Examples:
A common 608 skate bearing:
.. pythonscad-example::
from pybosl2.parts.ball_bearings import BearingType, BallBearings
BallBearings.ball_bearing(BearingType.BEARING_608).show()
"""
if trade_size is not None:
if isinstance(trade_size, str):
trade_size = BearingType.of(trade_size)
spec = BallBearings.ball_bearing_info(trade_size)
inner_diameter, outer_diameter, width, shield = (
spec.inner_diameter,
spec.outer_diameter,
spec.width,
spec.shielded,
)
if inner_diameter is None:
raise ValueError("ball_bearing(): must give inner_diameter.")
if outer_diameter is None:
raise ValueError("ball_bearing(): must give outer_diameter.")
if width is None:
raise ValueError("ball_bearing(): must give width.")
mid_d = (inner_diameter + outer_diameter) / 2
wall = (outer_diameter - inner_diameter) / 2 / 3
if shield:
result = (
tube(
inner_diameter=inner_diameter,
wall=wall,
height=width,
fn=fn,
fa=fa,
fs=fs,
)
| tube(
outer_diameter=outer_diameter,
wall=wall,
height=width,
fn=fn,
fa=fa,
fs=fs,
)
| tube(
inner_diameter=inner_diameter + 0.1,
outer_diameter=outer_diameter - 0.1,
height=(wall * 2 + width) / 2,
fn=fn,
fa=fa,
fs=fs,
)
)
else:
ball_cnt = int(math.floor(math.pi * mid_d * 0.95 / (wall * 2)))
races = tube(
inner_diameter=inner_diameter,
wall=wall,
height=width,
fn=fn,
fa=fa,
fs=fs,
) | tube(
outer_diameter=outer_diameter,
wall=wall,
height=width,
fn=fn,
fa=fa,
fs=fs,
)
races = races - torus(major_radius=mid_d / 2, minor_radius=wall, fn=fn, fa=fa, fs=fs)
balls = reduce(
operator.or_,
(
sphere(diameter=wall * 2, fn=fn, fa=fa, fs=fs).right(mid_d / 2).rotate([0, 0, i * 360 / ball_cnt])
for i in range(ball_cnt)
),
)
result = races | balls
result = Bosl2Solid(result.shape, size=[outer_diameter, outer_diameter, width])
return result.color(color) if color else result