A circle looks like an easy target for a cubic curve. Four symmetric segments, one for each quadrant, already appear circular at normal display sizes. The interesting part begins when the approximation must be measured: different control points minimize different errors, and the familiar constant is not optimal under every useful criterion.
The underlying Bézier curve construction supplies stable evaluation, subdivision, derivatives, and endpoint tangents. Here the geometry is specialized to circles and then extended to the rotated elliptical arcs used by SVG. In the reverse direction, a polynomial curve can be approximated by a tangent-continuous arc spline.
Why a Polynomial Bézier Curve Cannot Be a Circle
A polynomial Bézier curve has polynomial coordinate functions \(x(t)\) and \(y(t)\). An exact unit-circle parameterization would have to satisfy
\[ x(t)^2+y(t)^2=1 \]
as a polynomial identity. If either coordinate were nonconstant, the highest-degree terms of the two squares would have nonnegative squared coefficients and could not cancel over the real numbers. Therefore both coordinates would have to be constant. A nondegenerate circular arc is not a polynomial parametric curve.
Rational quadratic Bézier curves can represent circles exactly because their homogeneous weight introduces a denominator. Ordinary SVG cubic commands are polynomial, so approximation is unavoidable when an arc command must be converted to cubic commands.
A Symmetric Cubic for One Quadrant
Work with the first quadrant of the unit circle. Fix the endpoints and align the endpoint derivatives with the circle tangents:
\[ \mathbf P_0=(1,0),\qquad \mathbf P_1=(1,k),\qquad \mathbf P_2=(k,1),\qquad \mathbf P_3=(0,1). \]
Symmetry leaves one unknown, \(k\). Expanding the cubic Bernstein form gives
\[ \begin{aligned} x(t)&=1-3(1-k)t^2+(2-3k)t^3,\\ y(t)&=3kt+(3-6k)t^2+(3k-2)t^3. \end{aligned} \]
Move \(k\) below. The pale stroke is the exact quarter circle. The numerical readout reports the signed radial drift of the cubic, so a negative value is inside the circle and a positive value is outside.
The Standard Midpoint Construction
At \(t=1/2\), symmetry gives
\[ \mathbf B\left(\frac12\right) =\left(\frac{4+3k}{8},\frac{4+3k}{8}\right). \]
Requiring this midpoint to lie on the unit circle yields
\[ 2\left(\frac{4+3k}{8}\right)^2=1, \qquad k_{\mathrm{mid}}=\frac43(\sqrt2-1) \approx0.552284749831. \]
This is the standard quarter-circle constant. It is exact at both endpoints and the midpoint, preserves endpoint tangents, and has a maximum radial drift of approximately \(2.725300072\times10^{-4}\) radii. For a circle of radius 1000 pixels, that is about 0.273 pixels.
Measure the Error Before Optimizing It
The signed radial drift is
\[ \delta(t)=\sqrt{x(t)^2+y(t)^2}-1. \]
Goldapp instead works with the polynomial squared-radius error
\[ q(t)=x(t)^2+y(t)^2-1 =(1+\delta(t))^2-1 =\delta(t)(\delta(t)+2). \]
Since the radius \(1+\delta(t)\) is positive, \(q'(t)=2(1+\delta(t))\delta'(t)\). The two errors therefore have the same zeros and stationary parameters. Their magnitudes are not identical, however, so a minimax result must state whether it optimizes \(q\) or the Euclidean radial drift \(\delta\).
Three error objectives are easy to confuse:
- Interpolation constraints force selected points onto the circle.
- Minimax error minimizes \(\max_{0\leq t\leq1}|\delta(t)|\).
- Least-squares error minimizes an integral such as \(\int_0^1\delta(t)^2\,dt\).
A least-squares fit can have a smaller total squared error while still having a larger worst local deviation. For rendering, collision margins, and fabrication tolerances, the maximum geometric error is often the useful number.
Reduce the Symmetric Error to One Variable
The competing quarter-circle models can be placed in one symmetric two-parameter family:
\[ \mathbf P_0=(1,0),\qquad \mathbf P_1=(u,v),\qquad \mathbf P_2=(v,u),\qquad \mathbf P_3=(0,1). \]
Reflection across the line \(x=y\) maps parameter \(t\) to \(1-t\), so the squared-radius error is symmetric: \(q(t)=q(1-t)\). Every such polynomial can be written in terms of \(s=t(1-t)\), whose range on \([0,1]\) is \([0,1/4]\). Direct expansion gives
\[ q(t)=s\left(A+Bs+Cs^2\right), \]
with
\[ \begin{aligned} A&=6(u-1),\\ B&=9(u-1)^2+9v^2+6(v-u),\\ C&=-2(3u-3v-1)^2. \end{aligned} \]
This form separates the geometric constraints from the optimization. Fixing \(u=1\) makes the first control direction vertical and the last horizontal, so the cubic matches the circle tangents. Algebraically, it also forces \(A=0\), making \(q\) vanish to second order at both endpoints. The tangent-constrained family therefore has only the parameter \(v=k\). Allowing \(u\neq1\) restores a second degree of freedom but reduces the endpoint zeros to first order, which is exactly the small tangent mismatch in the Goldapp model.
Minimax constants are obtained by differentiating this cubic in \(s\), retaining stationary points in \([0,1/4]\), and solving for alternating extrema of equal absolute magnitude. Optimizing \(q\) remains algebraic; optimizing the radial drift \(\delta=\sqrt{1+q}-1\) uses the same stationary parameters but slightly different equal-magnitude equations. This is why the objective must be named together with each quoted constant.
Endpoint-Constrained Minimax
Keep the endpoints and endpoint tangents fixed, but stop requiring the midpoint to lie exactly on the circle. Numerically minimizing the maximum absolute radial drift gives
\[ k_{\mathrm{minimax}}\approx0.551915024494. \]
The error now alternates between nearly equal positive and negative extrema. This equioscillation is the expected signature of a minimax solution. The maximum drift falls to approximately \(1.960764696\times10^{-4}\) radii, about 28% below the standard construction. Unlike the midpoint construction, it does not pass exactly through the 45-degree point.
Endpoint-Constrained Least Squares
Keeping the same endpoints and tangent directions but minimizing the integrated squared radial drift gives
\[ k_{\mathrm{LS}}\approx0.551970381401, \qquad \int_0^1\delta(t)^2\,dt\approx1.768080329\times10^{-8}. \]
The integral is about 1.9% smaller than the minimax value, but the maximum drift rises to approximately \(2.064310090\times10^{-4}\) radii, about 5.3% above the minimax peak. Least squares is therefore appropriate when average squared deviation is the objective; it is not an improvement when a hard geometric tolerance controls acceptance.
Fixed Endpoints with Free Tangents
If endpoint positions remain mandatory but tangent agreement is relaxed, Goldapp's Chebyshev construction for the squared-radius error adds another degree of freedom. For a unit quarter circle, the symmetric controls are
\[ \mathbf P_0=(1,0),\qquad \mathbf P_1=(0.998978326,0.553177370),\qquad \mathbf P_2=(0.553177370,0.998978326),\qquad \mathbf P_3=(0,1). \]
Direct evaluation gives a maximum radial drift of approximately \(6.84415\times10^{-5}\) radii, about 65% below the tangent-constrained minimax model. The initial tangent misses the circle tangent by approximately 0.106 degrees. Adjacent quadrants therefore meet positionally but not tangentially: the composite is \(C^0\), not \(G^1\) or \(C^1\). This is useful only when lower radial error matters more than a smooth join.
A Freer Four-Segment Circle
If the four quadrant endpoints may move slightly away from the circle, one more improvement is possible. Write a symmetric first-quadrant segment as
\[ \mathbf P_0=(a,0),\qquad \mathbf P_1=(c,b),\qquad \mathbf P_2=(b,c),\qquad \mathbf P_3=(0,a). \]
A numerical minimax solution is
\[ a=1.00005507808,\qquad b=0.55342925736,\qquad c=0.99873327689. \]
Its maximum drift is approximately \(5.507808665\times10^{-5}\) radii, almost five times smaller than the standard construction. The price is semantic: the nominal cardinal points are no longer on the target circle. This model is excellent for drawing a complete isolated circle, but unsuitable for replacing an arc whose endpoints must join existing path segments exactly.
Higher Degree Means Higher Contact Order
Cubics are the practical default in SVG, but they are not the end of polynomial circle approximation. Ahn and Kim construct symmetric quartic and quintic Bézier curves whose derivatives agree with a circular arc to successively higher geometric orders. The cleanest derivation does not begin by expanding every coordinate. It begins with the circle's implicit equation.
Normalize the radius to one and define the squared-radius error
\[ \Phi(t)=\mathbf B(t)\mathbin{\cdot}\mathbf B(t)-1. \]
A curve that interpolates the circle at an endpoint has \(\Phi=0\) there. Tangent contact adds \(\Phi'=0\), curvature contact adds \(\Phi''=0\), and contact of order \(k\) is equivalent to
\[ \Phi(0)=\Phi'(0)=\cdots=\Phi^{(k)}(0)=0, \]
with the same conditions at \(t=1\). Symmetry makes the conditions at the second endpoint automatic. This converts geometric contact into scalar polynomial equations while avoiding an unknown reparameterization of the circle.
A Quartic with \(GC^3\) Contact
Let the unit arc sweep through \(\alpha\), where \(0<\alpha<\pi\), and write \(h=\alpha/2\). A symmetric tangent-matched quartic can be parameterized by one endpoint handle \(u\) and one midpoint radius \(\rho\):
\[ \begin{aligned} \mathbf b_0&=(1,0), & \mathbf b_1&=(1,u),\\ \mathbf b_2&=\rho(\cos h,\sin h),\\ \mathbf b_3&=(\cos\alpha+u\sin\alpha,\sin\alpha-u\cos\alpha), & \mathbf b_4&=(\cos\alpha,\sin\alpha). \end{aligned} \]
The endpoint and tangent conditions already give \(\Phi(0)=\Phi'(0)=0\). Since
\[ \mathbf B'(0)=4(\mathbf b_1-\mathbf b_0),\qquad \mathbf B''(0)=12(\mathbf b_2-2\mathbf b_1+\mathbf b_0), \]
imposing \(\Phi''(0)=2\bigl(\|\mathbf B'(0)\|^2+\mathbf B(0)\cdot\mathbf B''(0)\bigr)=0\) gives
\[ \boxed{\rho=\frac{3-4u^2}{3\cos h}.} \]
One parameter remains. Differentiating once more,
\[ \Phi'''(0)=2\left(\mathbf B(0)\cdot\mathbf B'''(0) +3\mathbf B'(0)\cdot\mathbf B''(0)\right), \]
and substituting \(\rho\) reduces \(\Phi'''(0)=0\) to a cubic equation in \(u\). There are two admissible positive roots. For a quarter circle, the larger root
\[ u_3\approx0.402437 \]
gives the better \(GC^3\) quartic, with Hausdorff distance approximately \(3.50\times10^{-5}\). As \(\alpha\to0\), its error is
\[ d_H=\frac{17-12\sqrt2}{2^{15}}\alpha^8+O(\alpha^{10}). \]
The eighth power is the central result: halving a sufficiently small sweep reduces the leading error by about \(2^8=256\), compared with \(2^6=64\) for a tangent-matched cubic.
Two Quartics with Eighth-Order Error
Endpoint contact is not the only way to spend the quartic's remaining freedom. Keep the same symmetric controls, require the curve midpoint to lie on the circular midpoint, and project \(\mathbf B(1/2)\) onto the angular bisector. This gives
\[ \boxed{\rho=\frac{8-5\cos h-4u\sin h}{3}.} \]
Kim and Ahn retain fourth-order implicit contact at the midpoint by imposing \(\Phi''(1/2)=0\). Together with symmetry and endpoint tangency, the resulting degree-eight error polynomial factors as
\[ \Phi(t)=\lambda t^2\left(t-\frac12\right)^4(t-1)^2. \]
Liu and coauthors instead interpolate two additional circular points by imposing \(\Phi(1/4)=0\). Symmetry gives the companion zero at \(t=3/4\), and the factorization becomes
\[ \Phi(t)=\lambda t^2\left(t-\frac14\right) \left(t-\frac12\right)^2 \left(t-\frac34\right)(t-1)^2. \]
Both constructions have eighth-order error for small sweeps, but they distribute the zeros differently. On a quarter circle, the midpoint-contact quartic has Hausdorff distance about \(2.03\times10^{-6}\); the five-point quartic lowers it to about \(1.11\times10^{-6}\). These values are substantially below the endpoint-\(GC^3\) quartic's \(3.50\times10^{-5}\), without increasing the degree. Equal-angle copies also meet with equal endpoint curvature, so they form a curvature-continuous quartic spline even though each individual segment retains only tangent contact with the circle at its outer endpoints.
const midpointContact = Bezier.polynomialArc(
center, radius, start, end, 4,
{ strategy: 'midpoint-contact' }
);
const fivePoint = Bezier.polynomialArc(
center, radius, start, end, 4,
{ strategy: 'five-point' }
); A Quintic with \(GC^4\) Contact
A symmetric quintic begins with
\[ \mathbf b_0=(1,0),\quad \mathbf b_1=(1,v),\quad \mathbf b_2=(\xi,\eta), \]
and obtains \(\mathbf b_3,\mathbf b_4,\mathbf b_5\) by reflecting these controls across the bisector of the arc. The first two nontrivial contact equations give
\[ \boxed{\xi=1-\frac54v^2,} \]
\[ \boxed{ \eta=\frac{\tfrac54(5+\cos\alpha)v^2+2\sin^2(\alpha/2)}{5v+\sin\alpha}. } \]
These formulas are worth deriving rather than transcribing: low-quality scans commonly interchange \(\xi\) and \(\eta\), or lose the factor 5 in the numerator. Direct substitution into \(\Phi''(0)=\Phi'''(0)=0\) detects either error immediately.
The remaining \(GC^4\) condition is
\[ \Phi''''(0)=2\mathbf B\cdot\mathbf B'''' +8\mathbf B'\cdot\mathbf B''' +6\mathbf B''\cdot\mathbf B''=0. \]
After inserting the controls, it becomes a sixth-degree equation in \(v\). It has at least two admissible roots. For a quarter circle, the more accurate branch has
\[ v_2\approx0.318858, \qquad d_H\approx3.68\times10^{-7}, \]
and the asymptotic error is \(O(\alpha^{10})\). The two extra powers relative to the quartic are the optimal order expected for a degree-five polynomial approximation.
Contact Order Is Not the Only Objective
The highest-contact curve is not always the smallest-error curve of the same degree. Ahn and Kim also optimize one-sided families. For a quarter circle, their best inward quartic \(GC^2\) curve has distance about \(3.55\times10^{-6}\), roughly ten times below the quartic \(GC^3\) result. Their best outward quintic \(GC^3\) branch reaches about \(2.95\times10^{-8}\), below the quintic \(GC^4\) result. The extra freedom lowers the peak error but sacrifices one endpoint contact condition.
This is the same modeling choice already visible among cubics: choose contact order when adjacent pieces must blend geometrically, and choose a constrained minimax family when the smallest Hausdorff envelope matters more. Degree, continuity, error sign, and error norm must all accompany a claim of best approximation.
const quartic = Bezier.polynomialArc(center, radius, start, end, 4);
const quintic = Bezier.polynomialArc(center, radius, start, end, 5); More Segments, Less Error
The quarter-circle result extends to any circular arc without guessing a new constant. Let a unit arc of total sweep \(\theta=2\alpha\) be symmetric about the x-axis:
\[ \mathbf P_0=(\cos\alpha,-\sin\alpha),\qquad \mathbf P_3=(\cos\alpha,\sin\alpha). \]
Place the two inner controls a distance \(h\) along the endpoint tangents. Their x-coordinate is \(\cos\alpha+h\sin\alpha\). At \(t=1/2\), the cubic weights are \(1/8,3/8,3/8,1/8\), so symmetry puts the Bézier midpoint on the x-axis at
\[ \begin{aligned} B_x\left(\frac12\right) &=\frac14\cos\alpha +\frac34(\cos\alpha+h\sin\alpha)\\ &=\cos\alpha+\frac34h\sin\alpha. \end{aligned} \]
Requiring this point to equal the circular midpoint \((1,0)\) gives
\[ h=\frac{4(1-\cos\alpha)}{3\sin\alpha} =\frac43\tan\frac\alpha2 =\frac43\tan\frac\theta4. \]
Lin, Ball, and Zheng call \(h\) the tangent magnitude parameter. Before choosing its value, the midpoint's signed radial error is already an affine function of \(h/r\):
\[ \frac{d_{ ext{mid}}}{r} =\cos\alpha+\frac34\frac{h}{r}\sin\alpha-1. \]
Its absolute value is therefore piecewise linear, with its corner exactly at the midpoint-interpolating value above. Their quarter-circle experiments found optimal tangent magnitude and peak-error regressions proportional to \(N^{-1.0133}\) and \(N^{-6.0020}\), respectively. Those exponents are empirical fits, not substitutes for direct error evaluation. The second one is useful confirmation of the analytic \(O(\theta^6)\) law because an equal subdivision has \(\theta\propto N^{-1}\).
A general circular segment with sweep \(\theta\) has endpoint controls placed along the tangents at distance
\[ kr,\qquad k=\frac43\tan\frac{\theta}{4}. \]
For this tangent-matched construction, the maximum radial error is \(O(|\theta|^6)\) as \(\theta\to0\). Halving a sufficiently small sweep therefore reduces its error by a factor approaching \(2^6=64\). This sixth-order behavior explains why increasing the segment count improves the approximation much faster than a generic cubic error estimate would suggest.
Rotating the symmetric construction to the requested start angle produces exactly the strategy: 'standard' curve returned by Bezier.arc. The quarter-circle constant is not a separate trick: substituting \(\theta=\pi/2\) gives \(k=\frac43(\sqrt2-1)\). For a complete circle divided into \(n\) equal pieces, \(\theta=2\pi/n\). More pieces rapidly reduce radial drift, at the cost of more path commands and control points.
Construct Controls Directly from Center and Endpoints
Absolute start and end angles are unnecessary when the center \(\mathbf C\) and endpoints \(\mathbf S,\mathbf E\) are already known. Let \(\mathbf a=\mathbf S-\mathbf C\) and \(\mathbf b=\mathbf E-\mathbf C\). For the signed minor sweep,
\[ \vartheta=\operatorname{atan2}(\mathbf a\times\mathbf b,\mathbf a\cdot\mathbf b), \qquad k=\frac43\tan\frac{\vartheta}{4}. \]
With \(R_{90}(x,y)=(-y,x)\), the cubic controls are then
\[ \mathbf P_0=\mathbf S,\qquad \mathbf P_1=\mathbf S+kR_{90}(\mathbf a),\qquad \mathbf P_2=\mathbf E-kR_{90}(\mathbf b),\qquad \mathbf P_3=\mathbf E. \]
The sign of the cross product selects clockwise or counterclockwise orientation. Endpoints alone do not identify a major arc, so this direct form is best used for already split pieces whose absolute sweep is at most 90 degrees.
function arcFromCenter(center, start, end) {
const ax = start.x - center.x;
const ay = start.y - center.y;
const bx = end.x - center.x;
const by = end.y - center.y;
const radius = Math.hypot(ax, ay);
if (!(radius > 0) ||
Math.abs(Math.hypot(bx, by) - radius) > 1e-9 * radius) {
throw new RangeError('Endpoints must lie on the same nonzero circle');
}
const sweep = Math.atan2(ax * by - ay * bx, ax * bx + ay * by);
if (Math.abs(sweep) > Math.PI / 2 + 1e-12) {
throw new RangeError('Split arcs larger than 90 degrees');
}
const k = 4 / 3 * Math.tan(sweep / 4);
return new Bezier([
start,
{ x: start.x - k * ay, y: start.y + k * ax },
{ x: end.x + k * by, y: end.y - k * bx },
end
]);
} Thin gray polygons connect the four controls of every cubic; the small outlined markers show the controls themselves. As the segment count grows, the inner controls move closer to their endpoints and the cubic pieces approach the circle locally. The displayed curve and exact circle are visually indistinguishable long before the numerical error reaches zero. Choose the segment count from an output-space tolerance, not from appearance at one zoom level. Absolute drift scales linearly with radius; relative drift does not.
Turn Relative Drift into an Output-Space Budget
Let \(E(\theta)\) be the maximum absolute radial drift of one standard unit-circle cubic with sweep \(\theta\). For a circle of radius \(r\), the maximum geometric displacement is
\[ e_{\mathrm{abs}}=rE(\theta). \]
To satisfy a tolerance \(\varepsilon\), split the requested sweep until \(rE(\theta)\leq\varepsilon\). The values below are computed from the same construction used by the interactive figure:
| Sweep per cubic | Maximum relative drift | Drift at radius 1000 px |
|---|---|---|
| 45 degrees | \(4.24553\times10^{-6}\) | 0.00425 px |
| 90 degrees | \(2.72530\times10^{-4}\) | 0.273 px |
For example, a 90-degree cubic exceeds one pixel only when the radius exceeds about 3669 pixels. This criterion is stable across display generations because it depends on the rendered radius and required tolerance, not on a label such as 4K. If the curve will later be transformed, evaluate the tolerance after that transform.
A chord spanning \(\theta\) has inward radial error \(r(1-\cos(\theta/2))\). One 90-degree chord therefore has about \(0.2929r\) error, more than one thousand times the standard cubic's radial drift for the same sweep. A full polygon needs about 135 equal chords merely to match the radial tolerance of four standard quarter-circle cubics. This comparison concerns geometric primitives; actual rendering cost still depends on how a graphics pipeline tessellates its paths.
From Circular Arcs to SVG Elliptical Arcs
An SVG elliptical arc uses endpoint syntax:
A rx ry x-axis-rotation large-arc-flag sweep-flag x y
The start point comes from the preceding path command. The center and parameter angles are implicit. Converting the arc to cubic Bézier segments therefore requires four steps:
- Translate the chord midpoint to the origin and rotate the ellipse axes into alignment.
- Increase radii when the declared ellipse is too small to reach both endpoints.
- Recover the flag-selected center, start angle, and signed sweep.
- Split the sweep into pieces no larger than 90 degrees and map each unit-circle cubic onto the ellipse.
Radius Correction
Let \((x',y')\) be the transformed start point in the midpoint coordinate system. SVG defines
\[ \lambda=\frac{x'^2}{r_x^2}+\frac{y'^2}{r_y^2}. \]
If \(\lambda>1\), no ellipse with the declared radii can pass through both endpoints. SVG requires both radii to be multiplied by \(\sqrt\lambda\). This is not an optional numerical fix; it is part of the path semantics.
Map the Unit Arc onto the Ellipse
After a unit-circle point \((u,v)\) has been computed, scale it by \(r_x,r_y\), rotate by the ellipse-axis angle \(\phi\), and translate it to the center \((c_x,c_y)\):
\[ \begin{pmatrix}x\\y\end{pmatrix} = \begin{pmatrix}\cos\phi&-\sin\phi\\\sin\phi&\cos\phi\end{pmatrix} \begin{pmatrix}r_xu\\r_yv\end{pmatrix} + \begin{pmatrix}c_x\\c_y\end{pmatrix}. \]
Affine transformations preserve Bézier curves. The transformed control points therefore describe the transformed cubic exactly; only the original circle-to-cubic replacement contributes approximation error.
Nonuniform scaling changes the error metric. If a unit-circle approximation has Euclidean error at most \(E\), scaling by \(r_x,r_y\) gives the conservative bound
\[ e_{\mathrm{ellipse}}\leq\max(r_x,r_y)E. \]
The true maximum may be smaller, but multiplying by the larger semiaxis is a safe way to select a segment count before measuring the transformed curve directly.
Parameter Angle Is Not Polar Angle
For an axis-aligned ellipse, the usual parameterization is \(\mathbf E(\varphi)=(r_x\cos\varphi,r_y\sin\varphi)\). Except for a circle, \(\varphi\) is not the geometric direction \(\vartheta\) of the radius vector. They satisfy
\[ \vartheta=\operatorname{atan2}(r_y\sin\varphi,r_x\cos\varphi), \qquad \varphi=\operatorname{atan2}(r_x\sin\vartheta,r_y\cos\vartheta). \]
Use the second equation when an API supplies geometric start and end directions but the cubic construction expects ellipse parameter angles. The two-argument \(\operatorname{atan2}\) preserves the quadrant and remains defined at vertical directions; a formula based only on \(\arctan(\tan\vartheta)\) does neither. For a rotated ellipse, first express the direction in the ellipse's local axis frame.
function ellipseParameterAngle(polarAngle, rx, ry) {
return Math.atan2(
rx * Math.sin(polarAngle),
ry * Math.cos(polarAngle)
);
} JavaScript Implementation
The Bezier library exposes both center-defined circular arcs and SVG endpoint-defined elliptical arcs. The latter returns an array because a large sweep must be split:
const curves = Bezier.fromSVGArc({
px: 120,
py: 40,
cx: 20,
cy: 90,
rx: 80,
ry: 45,
xAxisRotation: 25,
largeArcFlag: 0,
sweepFlag: 1,
strategy: 'minimax'
});
const commands = Bezier.arcToBezier({
px: 120,
py: 40,
cx: 20,
cy: 90,
rx: 80,
ry: 45,
xAxisRotation: 25,
largeArcFlag: 0,
sweepFlag: 1
}); fromSVGArc returns full Bezier instances. arcToBezier returns command-shaped objects with x1, y1, x2, y2, x, and y. Both use the endpoint-constrained minimax constant for exact 90-degree pieces by default. Pass strategy: 'standard' when midpoint interpolation is required, or strategy: 'least-squares' when integrated squared radial drift is the objective. On a noncircular ellipse, the affine image preserves endpoints and tangents, but an optimized circle control factor is not necessarily optimal under Euclidean distance measured after the nonuniform scaling.
A complete four-segment approximation is equally direct:
const standard = Bezier.approximateCircle(center, radius, {
strategy: 'standard'
});
const endpointExact = Bezier.approximateCircle(center, radius, {
strategy: 'minimax'
});
const leastSquaredDrift = Bezier.approximateCircle(center, radius, {
strategy: 'least-squares'
});
const fixedEndpoints = Bezier.approximateCircle(center, radius, {
strategy: 'c0-goldapp'
});
const smallestDrift = Bezier.approximateCircle(center, radius, {
strategy: 'relaxed'
}); The c0-goldapp strategy is defined only for exact 90-degree pieces and is rejected for other sweeps. It is available for center-defined arcs and four-segment circles, but not for SVG arc conversion, where preserving endpoint tangents is normally part of replacing a path segment without introducing visible corners.
Degenerate and Numerical Cases
- Zero \(r_x\) or \(r_y\) means the SVG arc is rendered as a line; the converter returns no cubic arc.
- Equal start and end points produce no arc under SVG endpoint semantics.
- Negative radii are replaced by their absolute values.
- Sweeps are split at 90 degrees or less to keep each cubic well-conditioned.
- The final cubic endpoint is assigned from the requested SVG endpoint, avoiding accumulated trigonometric drift.
- Angles close to an exact quadrant are treated as a quadrant, preventing accidental extra segments from floating-point noise.
Which Approximation Should Be Used?
| Requirement | Recommended model |
|---|---|
| Interpolate endpoints and the 45-degree midpoint | Standard midpoint |
| Preserve arc endpoints and minimize integrated squared radial drift | Endpoint-constrained least squares |
| Preserve arc endpoints and minimize maximum radial drift | Endpoint-constrained minimax |
| Preserve quarter-arc endpoints but allow tangent discontinuities | Goldapp C0 |
| Draw an isolated four-segment circle with the smallest drift here | Relaxed endpoints |
| Represent a circle exactly | Rational quadratic Bézier or native arc |
| Convert an SVG elliptical arc to cubic path commands | Endpoint-constrained segments of at most 90 degrees |
There is no universally best constant. The correct approximation follows from the constraints that downstream geometry must preserve and from the error norm that matters to the application.
Area and curvature are separate objectives. The exact signed sector area swept by a parametric curve is
\[ A=\frac12\int_0^1\bigl(x(t)y'(t)-y(t)x'(t)\bigr)\,dt. \]
Requiring \(\int_0^1 q(t)\,dt=0\) does not generally enforce this area, and minimizing radial drift does not necessarily minimize curvature variation. Applications concerned with mass properties, tool paths, or fair joins must choose those objectives explicitly.
References
- [Ahn1997]Young Joon Ahn and Hong Oh Kim, Approximation of Circular Arcs by Bézier Curves, Journal of Computational and Applied Mathematics 81, 1997, pages 145–163.
- [Lin2001]J. Lin, A. A. Ball, and J. J. Zheng, Approximating Circular Arcs by Bézier Curves and Its Application to Modelling Tooling for FE Forming Simulations, International Journal of Machine Tools and Manufacture 41(5), 2001, pages 703–717.
- [Kim2007]Seon-Hong Kim and Young Joon Ahn, An Approximation of Circular Arcs by Quartic Bézier Curves, Computer-Aided Design 39(6), 2007, pages 490–493.
- [Liu2012]Zhi Liu, Jie-qing Tan, Xiao-yan Chen, and Li Zhang, An Approximation Method to Circular Arcs, Applied Mathematics and Computation 219(3), 2012, pages 1306–1311.
- [Goldapp1991]Michael Goldapp, Approximation of Circular Arcs by Cubic Polynomials, Computer Aided Geometric Design 8(3), 1991.
- [Farin2002]Gerald Farin, Curves and Surfaces for CAGD: A Practical Guide, fifth edition, Morgan Kaufmann, 2002.
- [SVG2]World Wide Web Consortium, Scalable Vector Graphics (SVG) 2, Appendix B: Implementation Notes.