yaqwsx / PcbDraw

Convert your KiCAD board into a nicely looking 2D drawing suitable for pinout diagrams
MIT License
1.13k stars 90 forks source link

It does not work in Kicad version 7.0.1 #142

Open wiserst opened 1 year ago

wiserst commented 1 year ago

Hi, since Kicad version 7.0.1 (still a test build), Pcbdraw stopped working for me. When I go back to version 7.0.0 it works.

Command Prompt:


D:\Renda\Documents\KiCad\7.0>set PCBDRAW_INKSCAPE=C:\Program Files\Inkscape\bin\inkscape.com

D:\Renda\Documents\KiCad\7.0>pcbdraw plot "D:\Projects\PCB_designs\KiCad\Projects\WiSER\W220731 - ZOR-6 DISPLAY\W220731.01\W220731.01.kicad_pcb" "D:\Projects\PCB_designs\KiCad\Projects\WiSER\W220731 - ZOR-6 DISPLAY\W220731.01\W220731.01.png" --no-components --side front --dpi 800 Fontconfig error: Cannot load default config file: No such file: (null) Fontconfig error: Cannot load default config file: No such file: (null) Traceback (most recent call last): File "C:\Program Files\KiCad\7.0\bin\Lib\runpy.py", line 197, in _run_module_as_main return _run_code(code, main_globals, None, File "C:\Program Files\KiCad\7.0\bin\Lib\runpy.py", line 87, in _run_code exec(code, run_globals) File "D:\Renda\Documents\KiCad\7.0\3rdparty\Python39\Scripts\pcbdraw.exe__main.py", line 7, in File "C:\Program Files\KiCad\7.0\bin\Lib\site-packages\click\core.py", line 1130, in call return self.main(*args, kwargs) File "C:\Program Files\KiCad\7.0\bin\Lib\site-packages\click\core.py", line 1055, in main rv = self.invoke(ctx) File "C:\Program Files\KiCad\7.0\bin\Lib\site-packages\click\core.py", line 1657, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) File "C:\Program Files\KiCad\7.0\bin\Lib\site-packages\click\core.py", line 1404, in invoke return ctx.invoke(self.callback, ctx.params) File "C:\Program Files\KiCad\7.0\bin\Lib\site-packages\click\core.py", line 760, in invoke return callback(*args, **kwargs) File "D:\Renda\Documents\KiCad\7.0\3rdparty\Python39\site-packages\pcbdraw\ui.py", line 180, in plot image = plotter.plot() File "D:\Renda\Documents\KiCad\7.0\3rdparty\Python39\site-packages\pcbdraw\plot.py", line 1054, in plot plotter.render(self) File "D:\Renda\Documents\KiCad\7.0\3rdparty\Python39\site-packages\pcbdraw\plot.py", line 640, in render self._plotter.execute_plot_plan(to_plot) File "D:\Renda\Documents\KiCad\7.0\3rdparty\Python39\site-packages\pcbdraw\plot.py", line 1226, in execute_plot_plan action.action(action.name, os.path.join(tmp, svg_file)) File "D:\Renda\Documents\KiCad\7.0\3rdparty\Python39\site-packages\pcbdraw\plot.py", line 691, in _process_baselayer get_board_polygon( File "D:\Renda\Documents\KiCad\7.0\3rdparty\Python39\site-packages\pcbdraw\plot.py", line 418, in get_board_polygon elements.append(SvgPathItem(svg_element.attrib["d"])) File "D:\Renda\Documents\KiCad\7.0\3rdparty\Python39\site-packages\pcbdraw\plot.py", line 106, in init raise SyntaxError("Unsupported path element " + path_elems[0]) SyntaxError: Unsupported path element 138.73000

D:\Renda\Documents\KiCad\7.0>

yaqwsx commented 1 year ago

Could you share the board (or at least outline without components) where it fails? I struggle to reproduce the behavior.

wiserst commented 1 year ago

Yes, here is the whole project. Thank you. W220731.01.ZIP

Here is a generated png from PcbDraw and Kicad 7.0.0 W220731 01(PCB_Top)

set-soft commented 1 year ago

Hi @wiserst !

The problem is with the rectangle used for the edge cuts. As a workaround: replace it by 4 lines.

BTW: Using fonts for your PCB makes it hard to share with others. KiCad introduced fonts support, but lacks a mechanism to embed them.

set-soft commented 1 year ago

Hi @yaqwsx !

The problem is that KiCad 7.0.1 is generating polygon paths, in this case a rectangle:

M 78.7300,28.0000 138.7300,28.0000 138.7300,96.0000 78.7300,96.0000 Z

But it can be anything:

M 108.7300,56.0000 138.7300,96.0000 78.7300,96.0000 78.7300,28.0000 138.7300,28.0000 Z

set-soft commented 1 year ago

The following patch solves the problem:

diff --git a/kibot/PcbDraw/plot.py b/kibot/PcbDraw/plot.py
index 9dc45ba9..8df84469 100644
--- a/kibot/PcbDraw/plot.py
+++ b/kibot/PcbDraw/plot.py
@@ -408,7 +408,22 @@ def get_board_polygon(svg_elements: etree.Element) -> etree.Element:
     for group in svg_elements:
         for svg_element in group:
             if svg_element.tag == "path":
-                elements.append(SvgPathItem(svg_element.attrib["d"]))
+                path = svg_element.attrib["d"]
+                # Check if this is a closed polygon (KiCad 7.0.1+)
+                polygon = re.fullmatch(r"M ((\d+\.\d+),(\d+\.\d+) )+Z", path)
+                if polygon:
+                    # Yes, decompose it in lines
+                    polygon = re.findall(r"(\d+\.\d+),(\d+\.\d+) ", path)
+                    start = polygon[0]
+                    # Close it
+                    polygon.append(polygon[0])
+                    # Add the lines
+                    for end in polygon[1:]:
+                        path = 'M'+start[0]+' '+start[1]+' L'+end[0]+' '+end[1]
+                        elements.append(SvgPathItem(path))
+                        start = end
+                else:
+                    elements.append(SvgPathItem(path))
             elif svg_element.tag == "circle":
                 # Convert circle to path
                 att = svg_element.attrib

Is quite lame because it decompose the polygon ... and then the code recreates it. But has a small impact in the code.

set-soft commented 1 year ago

Ugh! Patch for the patch:

diff --git a/kibot/PcbDraw/plot.py b/kibot/PcbDraw/plot.py
index 8df84469..23b7d31f 100644
--- a/kibot/PcbDraw/plot.py
+++ b/kibot/PcbDraw/plot.py
@@ -408,12 +408,12 @@ def get_board_polygon(svg_elements: etree.Element) -> etree.Element:
     for group in svg_elements:
         for svg_element in group:
             if svg_element.tag == "path":
-                path = svg_element.attrib["d"]
+                p = svg_element.attrib["d"]
                 # Check if this is a closed polygon (KiCad 7.0.1+)
-                polygon = re.fullmatch(r"M ((\d+\.\d+),(\d+\.\d+) )+Z", path)
+                polygon = re.fullmatch(r"M ((\d+\.\d+),(\d+\.\d+) )+Z", p)
                 if polygon:
                     # Yes, decompose it in lines
-                    polygon = re.findall(r"(\d+\.\d+),(\d+\.\d+) ", path)
+                    polygon = re.findall(r"(\d+\.\d+),(\d+\.\d+) ", p)
                     start = polygon[0]
                     # Close it
                     polygon.append(polygon[0])
@@ -423,7 +423,7 @@ def get_board_polygon(svg_elements: etree.Element) -> etree.Element:
                         elements.append(SvgPathItem(path))
                         start = end
                 else:
-                    elements.append(SvgPathItem(path))
+                    elements.append(SvgPathItem(p))
             elif svg_element.tag == "circle":
                 # Convert circle to path
                 att = svg_element.attrib

I overlooked a variable name collision.

weikinhuang commented 5 months ago

hi, has there been an update for this?