I'm trying to work out a way to intrepret g-code into an SVG image. I can imagine to work with coordinates easily to draw straight lines, but I am struggling with arcs. I can't figure out how to interpret the I J system as an arc in SVG.
(ORIGIN=BOTTOM LEFT)
(METRIC)
G71
(RELATIVE)
G91
M16
(PART 1)
G00X-74.7Y585.5
M15
G01X-1.0Y0.0
G02X-735.2Y736.2I0.4J735.6
G01X10.0Y0.0
G01X0.0Y75.0
G01X501.2Y0.0
G01X0.0Y-75.0
G01X10.0Y0.0
G03X215.0Y-215.0I214.4J-0.6
G01X0.0Y-10.0
G01X75.0Y0.0
G01X0.0Y-501.2
G01X-75.0Y0.0
G01X0.0Y-10.0
M16
(PARK)
It's my understanding for the code above, it's relative, so I would start at -74,585 followed by moving -1,0 then start an arc that ends -735.2,736.2 away from the start of the arc. The arc centre would be based on the I and J information. As this is relative, is the I and J relative to the start of the arc?
For the centre of the arc, how would this translate to svg arcs? Am I right in thinking that for a SVG bezier curve (Q) the control point is on the 'outside' of the curve, whereas for the g-code the centre would be on the inside?
I can parse the data that I have and generate the following SVG:
<svg viewBox="-820 -35 4283 1441">
<path class="path" d="M-74,585 -75,585" style="stroke:black;stroke-width:5"></path>
<path class="path" d="M-75,585 Q -810 1321 -810 1321" style="fill:none;stroke:black;stroke-width:5"></path>
<path class="path" d="M-810 1321 -800,1321" style="stroke:black;stroke-width:5"></path>
<path class="path" d="M-800,1321 -800,1396" style="stroke:black;stroke-width:5"></path>
<path class="path" d="M-800,1396 -299,1396" style="stroke:black;stroke-width:5"></path>
<path class="path" d="M-299,1396 -299,1321" style="stroke:black;stroke-width:5"></path>
<path class="path" d="M-299,1321 -289,1321" style="stroke:black;stroke-width:5"></path>
<path class="path" d="M-289,1321 Q -74 1106 -74 1106 " style="fill:none;stroke:black;stroke-width:5"></path>
<path class="path" d="M-74 1106 -74,1096" style="stroke:black;stroke-width:5"></path>
<path class="path" d="M-74,1096 1,1096" style="stroke:black;stroke-width:5"></path>
<path class="path" d="M1,1096 1,595" style="stroke:black;stroke-width:5"></path>
<path class="path" d="M1,595 -74,595" style="stroke:black;stroke-width:5"></path>
<path class="path" d="M-74,595 -74,585" style="stroke:black;stroke-width:5"></path>
<path class="path" d="M-74,585 -74,585" style="stroke:red;stroke-width:10"></path>
</svg>
I've not added the script I'm using to generate this (written in PHP) as it's verbose and pulls data from a database so wouldn't really help. The orientation is wrong, but I can fix that up with a transform on the overall SVG. The lines responsible for the arc have the Q in them and it's the control point value that I can't for the life of me mathematically work out based on the I J values for the point in the g-code. Any help or advice would be greatly appreciated.
You cannot convert a circular arc, as described by a G02
or G03
command, into a faithfull quadratic bezier curve, as described by a Q
command - it would at best be an approximation. In addition there really is no need. SVG path commands include the A
command, which describes elliptical arcs. Its syntax is:
A rx ry x-axis-rotation large-arc-flag sweep-flag x y (absolute notation)
a rx ry x-axis-rotation large-arc-flag sweep-flag x y (relative notation)
This is a lot more complex than you need, because in can describe elliptical arcs that are rotated as well. In your case, the first two parameters, describing the elipses radii, are identical, and the third one is 0, because a rotated circle does not change.
What you need to do first is to determine the radius of the circle from the distance between the starting point and the center of the rotation. The center coordinate is relative to that starting point, so you can simply write
$r = hypot($I, $J)
The large arc flag and the sweep flag are needed to discern between the four possible solutions to draw an arc with a certain radius. The large arc flag describes wether the arc covers more than 180 degrees. If I understand the restrictions of CNC machinery right, this is not possible. Therefor the value should probably be 0
(false) - correct me if I am wrong. The sweep flag describes whether the arc goes clockwise or counterclockwise. So its value is 1
(true) for a G02
command, and 0
(false) for a G03
command.
If you use the relative a
command, the final x and y coordinates are simply the same as the X
and Y
values.
Together, the G-code command
G02X-735.2Y736.2I0.4J735.6
can be written as the path command d
attribute
d="M-75,585 a 735.6001 735.6001 0 0 1 -735.2,736.2"
As a final note, you can also write straight lines with relative coordinates if you use the l
command. G01X-1.0Y0.0
can be written both as
d="M-74,585 -75,585"
and
d="M-74,585 l -1,0"
Depending on your requirements, you can even combine multiple lines in one <path>
element, like this:
d="M-74,585 l -1,0 m 0,0 a 735.6001 735.6001 0 0 1 -735.2,736.2 m 0,0 l 10,0 ..."
with m 0,0
saying that the new line should start where the previous ended. Or you can also draw one, continuous line with multiple segments:
d="M-74,585 l -1,0 a 735.6001 735.6001 0 0 1 -735.2,736.2 l 10,0 ..."