imrishabh18/rp2040-motor-controller

An RP2040-based NEMA17 stepper-motor controller with USB-C programming and PD motor-power negotiation, DRV8825 dual H-bridge drive, current/temperature telemetry, protected power filtering, status RGB LED, buzzer alarm, and optional magnetic encoder.

Version
1.0.42
License
unset
Stars
3

scripts/copper_geometry.py

"""Trace segments matching the pinned circuit-json-to-gerber export semantics."""
from shapely.strtree import STRtree
from shapely.ops import unary_union


def subtract_drills(shapes, metadata, barrels, drills, layer_of):
    """Remove drilled-away copper and keep separated physical pieces separate."""
    drill_shapes = [g for g, _ in drills]
    tree = STRtree(drill_shapes)
    new_shapes, new_metadata, mapping = [], [], {}
    for i, (shape, meta) in enumerate(zip(shapes, metadata)):
        nearby = [drill_shapes[k] for k in tree.query(shape) if layer_of(meta) in drills[k][1]]
        cut = shape.difference(unary_union(nearby)) if nearby else shape
        pieces = []
        def collect(g):
            if g.is_empty:
                return
            if g.geom_type in ('MultiPolygon', 'GeometryCollection'):
                for piece in g.geoms:
                    collect(piece)
            elif g.area > 1e-12:
                pieces.append(g)
        collect(cut)
        mapping[i] = list(range(len(new_shapes), len(new_shapes) + len(pieces)))
        new_shapes.extend(pieces)
        new_metadata.extend([meta] * len(pieces))
    return new_shapes, new_metadata, [[n for i in ids for n in mapping[i]] for ids in barrels]

def trace_segments(route):
    for a, b in zip(route, route[1:]):
        start = end = layer = width = None
        if a['route_type'] == 'wire':
            start, layer, width = a, a['layer'], a['width']
            if b['route_type'] in ('wire', 'via'):
                end = b
            elif b['route_type'] == 'through_pad':
                end = b['start'] if b['start_layer'] == layer else b['end'] if b['end_layer'] == layer else None
        elif b['route_type'] == 'wire':
            end, layer, width = b, b['layer'], b['width']
            if a['route_type'] == 'via':
                start = a
            elif a['route_type'] == 'through_pad':
                start = a['end'] if a['end_layer'] == layer else a['start'] if a['start_layer'] == layer else None
        if start is None or end is None or (start['x'] == end['x'] and start['y'] == end['y']):
            continue
        yield (start['x'], start['y']), (end['x'], end['y']), layer, width