Skip to content

Instantly share code, notes, and snippets.

@kenkeiter
Last active July 6, 2022 16:52
Show Gist options
  • Select an option

  • Save kenkeiter/dd0a88c612eb60184d2f774b0b5e948a to your computer and use it in GitHub Desktop.

Select an option

Save kenkeiter/dd0a88c612eb60184d2f774b0b5e948a to your computer and use it in GitHub Desktop.

Revisions

  1. kenkeiter revised this gist Jul 6, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion kicad6_arrange.py
    Original file line number Diff line number Diff line change
    @@ -12,7 +12,7 @@
    #
    # >>> import arrange
    # >>> arrange.circular(['D13', 'D14', 'D15'], (100, 100), 10)
    # >>> arrange.circular(ref_range('D', 1, 10), (100, 100), 10)
    # >>> arrange.circular(arrange.ref_range('D', 1, 10), (100, 100), 10)

    def ref_range(prefix, start, end):
    """
  2. kenkeiter revised this gist Jul 6, 2022. 1 changed file with 18 additions and 0 deletions.
    18 changes: 18 additions & 0 deletions kicad6_arrange.py
    Original file line number Diff line number Diff line change
    @@ -12,6 +12,24 @@
    #
    # >>> import arrange
    # >>> arrange.circular(['D13', 'D14', 'D15'], (100, 100), 10)
    # >>> arrange.circular(ref_range('D', 1, 10), (100, 100), 10)

    def ref_range(prefix, start, end):
    """
    Generates a sequence of reference designators.
    Args:
    prefix (str): the prefix of the reference designator (for example, 'D')
    start (int): the start of the range
    end (int): the end of the range (including this number)
    Example:
    >>> rng = ref_range('D', 1, 5)
    >>> list(rng)
    ['D1', 'D2', 'D3', 'D4', 'D5]
    """
    for idx in range(start, end+1):
    yield prefix + str(idx)

    def circular(refs, center, radius, rotation_offset_deg=0, radius_offset_deg=0):
    """
  3. kenkeiter revised this gist Jul 6, 2022. 1 changed file with 21 additions and 11 deletions.
    32 changes: 21 additions & 11 deletions kicad6_arrange.py
    Original file line number Diff line number Diff line change
    @@ -11,35 +11,45 @@
    # something like the following:
    #
    # >>> import arrange
    # >>> arrange.circular((100, 100), 10, ['D13', 'D14', 'D15'])
    # >>> arrange.circular(['D13', 'D14', 'D15'], (100, 100), 10)

    def circular(center, radius, refs, rotation_offset_deg=0, radius_offset_deg=0):
    def circular(refs, center, radius, rotation_offset_deg=0, radius_offset_deg=0):
    """
    Place a set of footprints (as identified by a list of their reference
    designators `refs`) around a `center` point at a given `radius`, with
    optional part rotational offsets and a radius offset that shifts all
    components a set number of degrees of rotation.
    Args:
    center (tuple): a tuple containing two numbers (x, y) locating the center of the circle
    radius (float): a number describing the distance from `center` at which parts will be placed
    ref (iterable): an iterable (list, tuple, etc.) identifying the parts to be rotated
    roation_offset_deg (float): [optional] a fixed number of degrees by which to rotate each part
    radius_offset_deg (float): [optional] a fixed number of degrees by which all parts rotations' will be shifted
    refs (iterable): an iterable (list, tuple, etc.) containing strings
    identifying the parts to be rotated by their reference designators
    (i.e. `['D1', 'D2', 'D3']`)
    center (tuple): a tuple containing two numbers (x, y) locating the
    center of the circle
    radius (float): a number describing the distance from `center` at which
    parts will be placed
    roation_offset_deg (float): [optional] a fixed number of degrees by
    which to rotate each part in addition to the automatic rotation
    of the part to orient it toward the center of the circle
    radius_offset_deg (float): [optional] a fixed number of degrees by
    which all parts rotations' will be shifted around the radius of
    the circle
    """
    pcb = pcbnew.GetBoard()
    ref_count = len(refs)

    for i, led_ref in enumerate(refs):
    part = pcb.FindFootprintByReference(led_ref)
    for i, ref in enumerate(refs):
    part = pcb.FindFootprintByReference(ref)

    rad = (2 * math.pi) * ((i + 1) / len(refs)) + math.radians(radius_offset_deg)
    rad = (2 * math.pi) * ((i + 1) / ref_count) + math.radians(radius_offset_deg)

    new_pos = pcbnew.VECTOR2I(
    pcbnew.FromMM(center[0] + radius*math.cos(rad)),
    pcbnew.FromMM(center[1] + radius*math.sin(rad)))

    part.SetPosition(new_pos)
    part.SetOrientationDegrees(
    (((i + 1) / len(refs)) * -360) - rotation_offset_deg - radius_offset_deg)
    (((i + 1) / ref_count) * -360) - rotation_offset_deg - radius_offset_deg)

    # refresh the layout after performing the above operations
    pcbnew.Refresh()
  4. kenkeiter revised this gist Jul 6, 2022. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions kicad6_arrange.py
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,8 @@
    import pcbnew
    import math

    # Based upon https://bit.ly/3agYp7f by Greg Davill (@GregDavill on Twitter)
    #
    # To use this with KiCAD 6.x.x:
    # 1. Save this script in KiCAD's "scripting/plugins" directory as "arrange.py"
    # 2. Open your PCB and refresh plugins by navigating to
  5. kenkeiter created this gist Jul 6, 2022.
    43 changes: 43 additions & 0 deletions kicad6_arrange.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,43 @@
    import pcbnew
    import math

    # To use this with KiCAD 6.x.x:
    # 1. Save this script in KiCAD's "scripting/plugins" directory as "arrange.py"
    # 2. Open your PCB and refresh plugins by navigating to
    # Tools > External Plugins > Refresh Plugins
    # 3. Open the scripting console (Tools > Scripting Console) and execute
    # something like the following:
    #
    # >>> import arrange
    # >>> arrange.circular((100, 100), 10, ['D13', 'D14', 'D15'])

    def circular(center, radius, refs, rotation_offset_deg=0, radius_offset_deg=0):
    """
    Place a set of footprints (as identified by a list of their reference
    designators `refs`) around a `center` point at a given `radius`, with
    optional part rotational offsets and a radius offset that shifts all
    components a set number of degrees of rotation.
    Args:
    center (tuple): a tuple containing two numbers (x, y) locating the center of the circle
    radius (float): a number describing the distance from `center` at which parts will be placed
    ref (iterable): an iterable (list, tuple, etc.) identifying the parts to be rotated
    roation_offset_deg (float): [optional] a fixed number of degrees by which to rotate each part
    radius_offset_deg (float): [optional] a fixed number of degrees by which all parts rotations' will be shifted
    """
    pcb = pcbnew.GetBoard()

    for i, led_ref in enumerate(refs):
    part = pcb.FindFootprintByReference(led_ref)

    rad = (2 * math.pi) * ((i + 1) / len(refs)) + math.radians(radius_offset_deg)

    new_pos = pcbnew.VECTOR2I(
    pcbnew.FromMM(center[0] + radius*math.cos(rad)),
    pcbnew.FromMM(center[1] + radius*math.sin(rad)))

    part.SetPosition(new_pos)
    part.SetOrientationDegrees(
    (((i + 1) / len(refs)) * -360) - rotation_offset_deg - radius_offset_deg)

    pcbnew.Refresh()