Source code for svgen.shapes.chip

"""
A module for adding circuit chips to SVG documents.
"""

# internal
from svgen.cartesian.rectangle import Rectangle
from svgen.color.resolve import get_color
from svgen.element import Element
from svgen.element.circle import Circle
from svgen.element.path import Path
from svgen.element.rect import Rect
from svgen.shapes.pins import add_pins, corners_translated


[docs] def add_outline_pins( # pylint: disable=too-many-locals rect: Rect, count: int, color: str, stroke_width: int | float = 3.0, ) -> list[Element]: """Add some number of pins to a rectangle.""" assert rect.square result: list[Element] = [] h_stroke = stroke_width / 2.0 width = rect.width / 3.0 height = (width / count) * 3 / 2 pin_spacing = ( (rect.width - (2 * height) - (height * count)) / (count - 1) ) + height radius = (height / 2.0) - (h_stroke / 2.0) for corner, curr in corners_translated(rect, width, height): c_width = width if corner.vertical else height c_height = height if corner.vertical else width for _ in range(count): cmds = [ f"M {curr.x} {curr.y}", f"m {h_stroke / 2.0} {h_stroke / 2.0}", ] if corner.vertical: # left pins if corner.on_left: cmds += [ f"m {radius} 0", f"h {(c_width / 2.0) - (h_stroke + radius)}", f"m 0 {c_height - h_stroke}", f"h -{(c_width / 2.0) - (h_stroke + radius)}", f"a {radius} {radius} 0 0 1 -{radius} -{radius}", f"a {radius} {radius} 0 0 1 {radius} -{radius}", ] # right pins else: cmds += [ f"m {(c_width / 2.0) - h_stroke} 0", f"h {(c_width / 2.0) - (h_stroke + radius / 2.0)}", f"m 0 {c_height - h_stroke}", f"h -{(c_width / 2.0) - (h_stroke + radius / 2.0)}", f"m {(c_width / 2.0) - (h_stroke + radius / 2.0)} 0", f"a {radius} {radius} 0 0 0 {radius} -{radius}", f"a {radius} {radius} 0 0 0 -{radius} -{radius}", ] else: # top pins if corner.on_top: cmds += [ f"m 0 {radius}", f"m {c_width - h_stroke} 0", f"v {(c_height / 2.0) - (h_stroke + radius)}", f"m -{c_width - h_stroke} 0", f"v -{(c_height / 2.0) - (h_stroke + radius)}", f"a {radius} {radius} 0 0 1 {radius} -{radius}", f"a {radius} {radius} 0 0 1 {radius} {radius}", ] # bottom pins else: cmds += [ f"m 0 {(c_height / 2.0) - h_stroke}", f"m {c_width - h_stroke} 0", f"v {(c_height / 2.0) - (h_stroke + radius / 2.0)}", f"m -{c_width - h_stroke} 0", f"v -{(c_height / 2.0) - (h_stroke + radius / 2.0)}", f"m 0 {(c_height / 2.0) - (h_stroke + radius / 2.0)}", f"a {radius} {radius} 0 0 0 {radius} {radius}", f"a {radius} {radius} 0 0 0 {radius} -{radius}", ] result.append( Path.create( *cmds, attrib={ "fill": "none", "stroke": get_color(color), "stroke-width": stroke_width, }, ) ) curr = curr.translate( pin_spacing * corner.vector_dx, pin_spacing * corner.vector_dy ) return result
[docs] def add_outline_chip( box: Rectangle, pin_color: str = "gray", circle_color: str = None, pin_count: int = 3, debug: bool = False, stroke_width: int | float = 3.0, ) -> tuple[list[Element], Rect]: """ Add a circuit chip to the document based on the provided rectangle and other configurations (outline variant). """ result: list[Element] = [] has_circle = circle_color is not None body_ratio = 1 / 2 if has_circle else 3 / 4 body_width = box.to_square(body_ratio).width # Add a circle behind the body. if has_circle: assert circle_color is not None result.append( Circle.centered( box, attrs={ "stroke": get_color(circle_color), "fill": "none", "stroke-width": stroke_width, }, ) ) # Add the body. body = Rect.centered( box, body_ratio, body_ratio, None, rx=body_width / 6, ry=body_width / 6, ) result += add_outline_pins(body, pin_count, pin_color) result.append(body) if debug: result.extend(handle_debug(body)) return result, body
[docs] def handle_debug( rect: Rect, count: int = 10, radius: float = 1.0 ) -> list[Circle]: """Add points for debugging""" grid = rect.grid(count, count) result = [] for point in grid.points: result.append(Circle.create(point, radius, "orange")) return result
[docs] def add_chip( box: Rectangle, body_color: str = "black", pin_color: str = "gray", circle_color: str = None, pin_count: int = 3, debug: bool = False, ) -> tuple[list[Element], Rect]: """ Add a circuit chip to the document based on the provided rectangle and other configurations. """ result: list[Element] = [] has_circle = circle_color is not None body_ratio = 1 / 2 if has_circle else 3 / 4 body_width = box.to_square(body_ratio).width # Add a circle behind the body. if has_circle: assert circle_color is not None result.append(Circle.centered(box, color=circle_color)) # Add the body. body = Rect.centered( box, body_ratio, body_ratio, body_color, rx=body_width / 6, ry=body_width / 6, ) result += add_pins(body, pin_count, pin_color) result.append(body) if debug: result.extend(handle_debug(body)) return result, body