Skip to content

Instantly share code, notes, and snippets.

@eric-wood
Last active February 10, 2022 16:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eric-wood/4e94473899af4d18df85226be57dfa27 to your computer and use it in GitHub Desktop.
Save eric-wood/4e94473899af4d18df85226be57dfa27 to your computer and use it in GitHub Desktop.

Setting up affinity2kicad

Note that this assumes some familiarity with tools like Homebrew, the shell, and concepts like PATH.

Installing dependencies

You'll need Python 3 to continue; MacOS still ships with v2, although Python 3 is available through the commandline tools.

Set up bitmap2component_osx

Part of the conversion process uses a binary built by svg2shenzhen, which converts bitmaps to KiCad components. Affinity2kicad relies on this being in your $PATH somewhere.

You can grab the executable itself from the latest release of svg2shenzhen. Unzip it and toss the bitmap2component_osx executable somewhere on your $PATH.

Because of MacOs' security model and the lack of signing on this binary, we have to reassure the OS that this binary is safe to run. You can do this by invoking bitmap2component_osx from the command line, or double-clicking on the file in Finder. You'll get a pop-up saying it can't open it. From there go into Security & Privacy settings in System Preferences and click the button to run the binary anyways.

Usage

Python interface

Pop open the python REPL (python3 in your shell) in the affinity2kicad directory.

Replace $INPUT and $OUTPUT here with the absolute path to your SVG and desired .kicad_pcb output, respectively.

from affinity2kicad import convert
convert(source='$INPUT', title='your name here', rev='1').write('$OUTPUT')

CLI

I threw together a little CLI (see cli.py in this gist) to make conversion easy and fun!

Grab the file, make it executable, and toss it in your $PATH somewhere. I put mine in ~/bin/affinity2kicad.

Run affinity2kicad --help for info on how to use it.

Setting up your Affinity document

In Document Setup, change the DPI to 2540.

Affinity2kicad uses layer names to map your document to the resulting PCB; you can find a full mapping of these here.

Each layer can be an individual object, or a group with that name.

EdgeCuts is a bit of a special case, and the tool will kick it back unless you follow these guidelines:

  • If the board is rectangular (e.g. uses a <rect>) the rectangle must be nested inside a group named EdgeCuts
  • If the board is a <path> (e.g. a rounded rect or other shape) it cannot be in a group and must be named EdgeCuts directly
  • The EdgeCuts layer must be located at 0,0

This is a bit confusing and I think is likely a bug, but easy enough to work around. Don't be afraid to play with the SVG output to make this work!

Exporting

From the Export menu choose "SVG," and make sure "Export text as curves" is enabled.

You should be good to go with these settings, but feel free to play around a bit if things are acting up.

Examples

If you get lost, the panel for Castor and Pollux was made using this process and makes for a great reference!

Check out the .afdesign and SVG files here. Note that the SVG output from the Affinity file won't actually work out of the box due to the EdgeCuts oddities mentioned above, and you'll want to rename that layer and nest it in a group named EdgeCuts in order for it to work.

#!/usr/bin/env python3
import argparse
import os
import subprocess
from affinity2kicad import convert
def build():
parser = argparse.ArgumentParser(
description="Convert Affinity Designer SVG to KiCad PCB")
parser.add_argument('svg', help='input SVG file')
parser.add_argument('--output', '-o', help='output destination')
parser.add_argument('--title', '-t', help='PCB title')
parser.add_argument('--revision', '-r', help='PCB revision', default='0')
parser.add_argument(
'--open', '-O', help='Open PCB after creation', action="store_const", const=True, default=False)
args = parser.parse_args()
(base_path, input_filename) = os.path.split(args.svg)
(name, _) = os.path.splitext(input_filename)
default_output_path = os.path.join(base_path, f'{name}.kicad_pcb')
output_path = args.output or default_output_path
title = args.title or name
document = convert(source=args.svg, title=title, rev=args.revision)
document.write(output_path)
if args.open:
subprocess.run(["/usr/bin/open", "--", output_path])
if __name__ == '__main__':
build()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment