Source code for jitxlib.landpatterns.twopin.radial

from collections.abc import Iterable
from typing import override

from jitx.shapes import Shape
from jitx.shapes.composites import plus_symbol
from jitx.shapes.primitive import Circle, Polygon
from jitx.shapes.shapely import ShapelyGeometry
from jitx.toleranced import Toleranced
from jitx.transform import Transform

from .. import LandpatternGenerator
from ..courtyard import ExcessCourtyard
from ..grid_layout import GridPosition, LinearNumbering
from ..ipc import DensityLevel
from ..leads import THLead
from ..pads import GridPadShapeGeneratorMixin, IPCTHPadConfig
from ..silkscreen.outlines import OutlineGenerator, SilkscreenOutline
from .smt import CathodeAnodeNumbering


# Minimum size of the silkscreen plus symbol polarity marker
MIN_PLUS_SIZE = 0.75
# Minimum height of the silkscreen triangle polarity marker
MIN_TRI_HEIGHT = 0.5


[docs] class RadialTwoPinBase(GridPadShapeGeneratorMixin, LandpatternGenerator): _num_rows: int = 2 _num_cols: int = 1 __lead: THLead __lead_spacing: Toleranced def __init__(self, lead: THLead, lead_spacing: Toleranced): super().__init__() self.pad_config(IPCTHPadConfig()) self.__lead = lead self.__lead_spacing = lead_spacing def _pad_shape(self, pos: GridPosition) -> Shape: return Circle(diameter=self.__lead.width.typ) @override def _generate_layout(self) -> Iterable[GridPosition]: half_spacing = self.__lead_spacing.typ / 2 return ( GridPosition(0, 0, Transform.translate(0.0, half_spacing)), GridPosition(1, 0, Transform.translate(0.0, -half_spacing)), )
[docs] class RadialOutline(OutlineGenerator): def __init__(self, polarized: bool = False): super().__init__() self.__polarized = polarized
[docs] @classmethod def plus_size_ratio(cls, density_level: DensityLevel) -> float: match density_level: case DensityLevel.A: return 0.25 case DensityLevel.B: return 0.20 case DensityLevel.C: return 0.15
[docs] @override def make_shape(self, target: SilkscreenOutline) -> Shape: line_width = self._line_width(target) clearance = target._silkscreen_soldermask_clearance pb = target._package_body() dl = target._density_level envelope = pb.envelope(dl).to_shapely() outline = envelope.buffer(clearance + line_width / 2).boundary.buffer( line_width / 2 ) if self.__polarized: minx, miny, maxx, maxy = envelope.bounds h2 = (maxy - miny) / 2 + clearance + line_width width = maxx - minx plus_size_ratio = self.plus_size_ratio(dl) plus_len = max(MIN_PLUS_SIZE, plus_size_ratio * width) plus_y = ( h2 + plus_len / 2.0 + 1.5 * line_width ) # 0.5 for the plus' line cap plus_shape = Transform.translate(0.0, plus_y) * plus_symbol( plus_len, line_width ) # psr = self.plus_size_ratio(target._density_level) thickness = 2.5 * line_width height = h2 + thickness base = height * 0.5 tri = Polygon( elements=[(0.0, 0.0), (-base, -height), (base, -height)] ).to_shapely() thickcl = clearance + line_width + thickness / 2 thick = envelope.buffer(thickcl).boundary.buffer(thickness / 2) outline = outline.union(thick.intersection(tri.g)).union( plus_shape.to_shapely().g ) return ShapelyGeometry(outline)
[docs] class RadialTwoPinDecorated(SilkscreenOutline, ExcessCourtyard, RadialTwoPinBase): def __base_init__(self): super().__base_init__() self.silkscreen_outline(RadialOutline())
[docs] class PolarizedRadialTwoPin(CathodeAnodeNumbering, RadialTwoPinDecorated): def __base_init__(self): super().__base_init__() self.silkscreen_outline(RadialOutline(polarized=True))
[docs] class RadialTwoPin(LinearNumbering, RadialTwoPinDecorated): pass