# Proof: SVG Arc to GCode G2 and G3

The SVG arc command consists of

A rx ry x-axis-rotation large-arc-flag sweep-flag x y
• rx: Ellipse radius of x-axis
• ry: Ellipse radius of y-axis
• x-axis-rotation: Coordinate system rotation in degrees
• large-arc-flag: Flag if large or small circle should be taken
• sweep-flag: Flag on which side of the line between start and end should the circle is drawn
• x: The final x-coordinate
• y: The final y-coordinate

For the case that $$r_x\neq r_y$$, we can only sample from the path and interpolate it linearly. But for the case that $$r_x=r_y$$, it’s possible to improve the gcode by using G2 and G3. In general, the syntax of G2 and G3 are

G2 I<offset> J<offset> R<radius> [X<pos>] [Y<pos>]
G3 I<offset> J<offset> R<radius> [X<pos>] [Y<pos>]
• I: An offset from the current X position to use as the arc center
• Y: An offset from the current Y position to use as the arc center
• R: The radius from the current XY position to use as the arc center
• X: The final x-coordinate
• Y: The final y-coordinate

The combination (I, J) or R are exclusive. As an example, an arc can be drawn like this with (I, J) offset or via radius R:

## Derivation

In this derivation, the use of the R parameter is ignored, and the gcode is fed with the (I, J) tuple.

Let’s say $$\mathbf{S}$$ is the absolute starting point of the SVG arc path and $$\mathbf{E}$$ the absolute ending point of the SVG arc path. The points are connected with the vector $$\mathbf{a}=\mathbf{E}-\mathbf{S}$$.

The point $$\mathbf{M} = \frac{1}{2}(\mathbf{S}+\mathbf{E})$$ is the mid-point between start and end. On this point, we can construct an orthogonal vector $$\mathbf{v}$$ to our desired center $$\mathbf{C}$$. The length $$|\mathbf{v}|$$ can be determined using Pythagorean theorem:

$|\mathbf{v}| = \sqrt{r^2 - \frac{1}{4}|\mathbf{a}|^2}$

Now the vector $$\mathbf{v}$$ can be found with the perp operator:

$\mathbf{v} = \mathbf{\hat{a}}^\perp |\mathbf{v}|$

Finally, the center (I, J) can be found with

$\begin{array}{rl} (I, J) =& \mathbf{M} \pm \mathbf{v} - \mathbf{S}\\ =& \mathbf{M} \pm \mathbf{\hat{a}}^\perp |\mathbf{v}| - \mathbf{S}\\ =& \frac{1}{2}(\mathbf{S}+\mathbf{E}) - \mathbf{S} \pm \frac{\mathbf{{a}}^\perp}{|\mathbf{a}|} \sqrt{r^2 - \frac{1}{4}|\mathbf{a}|^2}\\ =& \frac{1}{2}(\mathbf{E} - \mathbf{S}) \pm \mathbf{{a}}^\perp \sqrt{\frac{r^2}{|\mathbf{a}|^2} - \frac{1}{4}}\\ =& \frac{1}{2}\left(\mathbf{a} \pm \mathbf{{a}}^\perp \sqrt{\frac{4r^2}{\mathbf{a}\cdot\mathbf{a}} - 1}\right)\\ \end{array}$

For which the positive part of the equation is used when the sweep-flag and large-arc-flag differ $$f_S\neq f_A$$ and the negative part is used for $$f_S=f_A$$.

The remaining question is to decide if we need to draw the circle clockwise or counter-clockwise, which is determined by the direction the circle is drawn - or simply if the sweep-flag $$f_S=1$$.

## Pseudo-Code

func arcToGCode(S, E, r, fS, fA) {

a = {
x: E.x - S.x,
y: E.y - S.y
}

aP = fS != fA ? {
x: -a.y,
y: a.x
} : {
x: a.y,
y: -a.x
}

w = sqrt(4 * r * r / (a.x * a.x + a.y * a.y) - 1)

I = (a.x + aP.x * w) / 2
J = (a.y + aP.y * w) / 2

if (fS != 1)
return "G2 X" + E.x + " Y" + E.y + " I" + I + " J" + J
else
return "G3 X" + E.x + " Y" + E.y + " I" + I + " J" + J
}