JarrettR/Stretch

Only output to SVG works with KiCad 6

trholding opened this issue ยท 11 comments

Only output to SVG works in KiCad 6. Changes can't be imported. I get and assert error.

Where do I start if I wanted to hack in KiCad 6 support?

Did a little bit of investigation -

The issue is the From_PCB() method of arc.py

The different KiCad file format for gr_arc are these:
5: (gr_arc (start 91.3218 93.4778) (end 85.471801 93.527799) (angle 90) (layer Edge.Cuts) (width 0.05) (tstamp 61D93C88))
6: (gr_arc (start 85.471801 93.527799) (mid 87.149871 89.376581) (end 91.271801 87.627801) (layer "Edge.Cuts") (width 0.05) (tstamp 00000000-0000-0000-0000-000061d93c88))

Looks like 6 might have done away with the "angle" field and replaced it with "mid", so this will require a little bit of math to get it into the right SVG format.

Thanks Jarrett. Is there anything I can do to help you?

The KiCad source kindly provides conversion routines https://gitlab.com/kicad/code/kicad/-/blob/master/libs/kimath/src/geometry/shape_arc.cpp#L204

Dunno if those are available though the API but you can at least reproduce the algorithm this way

Looks like 6 might have done away with the "angle" field and replaced it with "mid", so this will require a little bit of math to get it into the right SVG format.

There may be a mathematical hint for KiCad 6 in "Making arcs" section on the following page:

https://mitxela.com/projects/melting_kicad_2

For the conversion process, there are four functions in each shape type. We're looking at arc.py for this one.

When run on a PCB file, the From_PCB() function converts the arc to an internal object, and then To_SVG() converts that object to SVG tags (which are really just XML). Converting to SVG back to PCB is basically the same thing, with From_SVG() and To_PCB().

I'm trying to keep this compatible with KiCad 5 (as well as 6 support, obviously) so there are a few ways we could handle both cases:

  • Adding a field to the SVG arc tag specifying KiCad6-style arcs instead of KiCad5-style arcs
  • Reading the KiCad version metadata and then passing it all the way to the arc conversion functions
  • Detecting the version of the python pcbnew library that is currently loaded

I think I like option 3 best, particularly if it's enclosed in a try block so that it can fall back to KiCad 5 if the library isn't loaded (ie. the plugin is being run standalone).

That would entail the KiCad version detection to only be run in the To_PCB() function. The From_PCB() function will need to detect whether start/end/angle exist or start/mid/end and convert to the internal object format (which doesn't care about version).
The SVG functions don't need to be touched at all, assuming the internal format doesn't change.

All of this is assuming that the PCBNew library is able to return what version of KiCad it's on. I would assume so! But I haven't yet looked into it.

I like the 3rd option too. But a fork for 6 is viable too.

I haven't worked on a Kicad plugin ever. This is going to be the first time. I'm studying a bit of https://docs.kicad.org/doxygen-python/namespacepcbnew.html and sources of various plugins to understand. I'll be working on a local fork and if there is any progress, I'll post it here.

Did a quick-and-dirty conversion for the different KiCad 6 arcs here:
https://github.com/JarrettR/Stretch/tree/kicad6

There's an issue with the conversion to SVG algorithm:
image

But the gist of how it could work is there. It no longer errors out. Properly setting it up to work with KiCad 5 stuff will also happen

That's pretty cool. I guess the rest boils down to maths! I'll check it out in a few minutes.

Edit: I confirm that output to SVG works. Output to SVG when tracks are filleted, resemble your board edges - concave. To PCB doesn't seem to work.

Encountered a bug. If changes are made on PCB but not saved and then To SVG is selected, it errors.

Encountered a bug when using teardrop plugin and its zones. In that case To SVG errors out.

https://github.com/JarrettR/Stretch/blob/kicad6/Stretch/kiplug/arc.py#L223
This code can be so much simpler. No need for any trigonometry, just linear calculations and one square root (for the radius) are enough. I'll take a crack at it tomorrow. Besides there should already be something in Kicad for this in order to even do things like render it on screen.

This is fixed