main
John Lauer Component files 3/3 5a1989d 2d ago
"""AI-created simplified 3D model of Amphenol 10164227-1001A1RLF (BergStak 0.40 mm board-to-board
receptacle, 100 positions, 1.5 mm stack, no hold-down), built from Amphenol drawing
10164227 rev C, sheet 1 (body A = 22.60, contact span B = 19.60, width 3.00 body / 3.38 over tails,
height 1.45, contact pitch 0.40, tail width 0.12, tail coplanarity 0.05).

Frame: Adom Z-up, millimetres, seating plane z = 0 (contact tails), origin = body centre, which is
also the footprint origin. Model y = -(KiCad y). Pad n of the footprint is at KiCad
x = 9.8 - 0.4 * floor((n - 1) / 2), odd pads at KiCad y = -1.32 (model y = +1.32), even at +1.32.

Simplifications: the housing is a box with one mating cavity and a split central island; contacts are
drawn as a tail on the board plus a strip on the cavity wall; no moulded marks (the drawing does not
tie any marking to a contact number).

Run: python 10164227-1001a1rlf_model.py <out.step>   (see the modes at the end)
"""
import sys
import cadquery as cq

N_PER_ROW = 50
P = 0.40
A = 22.60          # housing length
W_BODY = 3.00      # housing width
W_TAILS = 3.38     # width over contact tails
H = 1.45           # mated-side height above the seating plane
STANDOFF = 0.05    # housing underside above the tail plane (drawing 0.05 +0.08/-0.05)
TAIL_W = 0.12
TAIL_T = 0.10
X0 = 9.8           # first contact x (B / 2)

housing = (cq.Workplane("XY").box(A, W_BODY, H - STANDOFF, centered=(True, True, False))
           .translate((0, 0, STANDOFF)))
cavity = (cq.Workplane("XY").box(A - 2.0, 2.30, 1.05, centered=(True, True, False))
          .translate((0, 0, H - 1.05)))
housing = housing.cut(cavity)
for sx in (-1, 1):
    island = (cq.Workplane("XY").box(9.40, 0.80, 0.95, centered=(True, True, False))
              .translate((sx * (0.5 + 4.70), 0, H - 1.05)))
    housing = housing.union(island)

contacts = None
for row, sy in ((0, 1), (1, -1)):          # model +y row = KiCad -y = odd pads
    for i in range(N_PER_ROW):
        x = X0 - i * P
        tail = (cq.Workplane("XY").box(TAIL_W, (W_TAILS - W_BODY) / 2 + 0.25, TAIL_T,
                                       centered=(True, False, False))
                .translate((x, 0, 0)))
        tail = tail.translate((0, W_BODY / 2 - 0.25, 0)) if sy > 0 else \
            tail.mirror("XZ").translate((0, -(W_BODY / 2 - 0.25), 0))
        strip = (cq.Workplane("XY").box(TAIL_W, 0.06, 0.85, centered=(True, True, False))
                 .translate((x, sy * (2.30 / 2 - 0.03), H - 1.05 + 0.10)))
        c = tail.union(strip)
        contacts = c if contacts is None else contacts.union(c)

# Modes:
#   <out.step>                      plain model (housing + contacts)
#   --body-only <out.step>          housing only, used as the input of the MPN etch: the etch planner
#                                   otherwise takes the protruding contact tails as the side face
#   --graft <etched-body.step> <out.step>
#                                   the etched housing (adom-aiflow-etch output, colours and the
#                                   Adom.LaserEtch group kept) plus the contacts, as the etched model
args = sys.argv[1:]
if args[0] == "--body-only":
    asm = cq.Assembly(name="10164227-1001A1RLF")
    asm.add(housing, name="housing", color=cq.Color(0.08, 0.08, 0.09))
    out = args[1]
elif args[0] == "--graft":
    asm = cq.Assembly(name="10164227-1001A1RLF")
    asm.add(cq.Assembly.importStep(args[1]), name="etched_housing")
    asm.add(contacts, name="contacts", color=cq.Color(0.86, 0.70, 0.30))
    out = args[2]
else:
    asm = cq.Assembly(name="10164227-1001A1RLF")
    asm.add(housing, name="housing", color=cq.Color(0.08, 0.08, 0.09))
    asm.add(contacts, name="contacts", color=cq.Color(0.86, 0.70, 0.30))
    out = args[0]
asm.export(out)
sys.argv[1] = out
print("OK", sys.argv[1])