Converting paths to circles in Inkscape

Or alternatively: how to get svg2shenzhen to recognize your drill paths as drill holes

(My) rationale: there is an Inkscape extension called svg2shenzhen. This extension creates Gerber and KiCad files that can be used to create printed circuit boards, from standard SVG files. Also, this extension has a funny name. Older, DIY printed circuit boards are just a high-DPI bitmap. Using Inkscape and this extension, you can trace the bitmap and then convert it to Gerber. However, most PCBs (especially old PCBs) need to have holes drilled. The drill locates are just circles in the bitmap, and after tracing, they’re just paths. The svg2shenzhen extension (at the time of this writing) detects circles in a certain layer as locations that need to be drilled, but not paths.

I’m not an Inkscape expert, but AFAIK Inkscape (at the time of this writing) doesn’t have a built-in tool to convert (mostly) circular paths to circles. So I wrote a simple extension that does this! It works fine on Linux. Not so sure about Windows.

Extensions are made of only two files, a file that describes the extension, and the extension code (which is in Python in many cases). These two files just have to be placed into the location shown in Edit -> Preferences -> System -> User extensions, which in my case is ~/.config/inkscape/extensions/.

Here are the two files, you can copy them into a text editor like Kate or gedit or Notepad, what have you, and save them into the above directory. I recommend keeping my file names, path2circle.inx and Note, some skeleton code in was generated by ChatGPT, though it was quite wrong. That’s where some of the verbose comments and extraneous code came from.


<?xml version="1.0" encoding="UTF-8"?>
            <submenu name="Custom"/>
        <command location="inx" interpreter="python"></command>

import inkex
from inkex import Circle

class Path2Circle(inkex.EffectExtension):
    def effect(self):
        # Iterate through all the selected objects in the SVG
        for node in self.svg.selection:
            # Check if the object is a path (or any other object type)
            if node.tag.endswith("path"):
                # Get the bounding box of the object
                x, y, width, height = self.get_object_dimensions(node)
                x = x.minimum
                y = y.minimum
                # with open('/path/to/debug/directory/debug_output.txt', 'a') as f:
                    # print(f"Object Dimensions: x={x}, y={y}, width={width}, height={height}", file=f)
                layer = self.svg.get_current_layer()
                diameter = min(width, height)
                layer.add(self.add_circle(x, y, diameter/2))

    def add_circle(self, x, y, radius):
        """Add a circle at the given location"""
        elem = Circle() = (x+radius, y+radius)
        elem.radius = radius
        return elem

    def get_object_dimensions(self, object_node):
        # Get the bounding box of the object
        bbox = object_node.bounding_box()

        # Extract the bounding box coordinates
        x = bbox.x
        y = bbox.y
        width = bbox.width
        height = bbox.height

        return x, y, width, height

if __name__ == '__main__':

To use the extension, you probably first need to restart Inkscape. (You do not need to restart Inkscape after changing the extension, however.) Select all the paths you’d like to convert, and then hit Extensions -> Custom -> Path2Circle. Note: the extension doesn’t actually care if the paths even remotely look like circles, so make sure to select the correct paths. You can easily modify the extension to calculate the radius differently, or e.g. replace paths with other objects, such as squares, rectangle, or ellipses. Let me know if you need help doing that.

Leave a Reply

Your email address will not be published.