diff --git a/docs/03-plugins/convert-path-data.mdx b/docs/03-plugins/convert-path-data.mdx
index 04c303de5..66848688f 100644
--- a/docs/03-plugins/convert-path-data.mdx
+++ b/docs/03-plugins/convert-path-data.mdx
@@ -31,7 +31,7 @@ svgo:
description: Number of decimal places to round to, using conventional rounding rules.
default: 5
smartArcRounding:
- description: Round the radius of circular arcs more when the effective change (measured with the sagitta) is under the error.
+ description: Round the radius of circular arcs when the effective change is under the error. The effective change is determined using the sagitta of the arc.
default: true
removeUseless:
description: Remove redundant path commands that don't draw anything.
diff --git a/plugins/convertPathData.js b/plugins/convertPathData.js
index e70e6a31a..2a6c66507 100644
--- a/plugins/convertPathData.js
+++ b/plugins/convertPathData.js
@@ -407,8 +407,6 @@ function filters(
var sdata = data,
circle;
- const sagitta = command === 'a' ? calculateSagitta(data) : undefined;
-
if (command === 's') {
sdata = [0, 0].concat(data);
@@ -645,16 +643,12 @@ function filters(
// round arc radius more accurately
// eg m 0 0 a 1234.567 1234.567 0 0 1 10 0 -> m 0 0 a 1235 1235 0 0 1 10 0
- if (
- params.smartArcRounding &&
- command === 'a' &&
- sagitta !== undefined &&
- precision
- ) {
+ const sagitta = command === 'a' ? calculateSagitta(data) : undefined;
+ if (params.smartArcRounding && sagitta !== undefined && precision) {
for (let precisionNew = precision; precisionNew >= 0; precisionNew--) {
const radius = toFixed(data[0], precisionNew);
const sagittaNew = /** @type {number} */ (
- calculateSagitta([radius, radius].concat(data.slice(2)))
+ calculateSagitta([radius, radius, ...data.slice(2)])
);
if (Math.abs(sagitta - sagittaNew) < error) {
data[0] = radius;
@@ -1100,15 +1094,16 @@ function isCurveStraightLine(data) {
* Calculates the sagitta of an arc if possible.
*
* @type {(data: number[]) => number | undefined}
+ * @see https://wikipedia.org/wiki/Sagitta_(geometry)#Formulas
*/
function calculateSagitta(data) {
- const rx = data[0],
- ry = data[1],
- distance = Math.sqrt(Math.pow(data[5], 2) + Math.pow(data[6], 2));
+ if (data[3] === 1) return undefined;
+
+ const [rx, ry] = data;
if (Math.abs(rx - ry) > error) return undefined;
- if (distance / 2 > rx) return undefined;
- if (data[3] == 1) return undefined;
- return rx - Math.sqrt(Math.pow(rx, 2) - 0.25 * Math.pow(distance, 2));
+ const chord = Math.sqrt(data[5] ** 2 + data[6] ** 2);
+ if (chord > rx * 2) return undefined;
+ return rx - Math.sqrt(rx ** 2 - 0.25 * chord ** 2);
}
/**
diff --git a/test/plugins/convertPathData.14.svg b/test/plugins/convertPathData.14.svg
index 2b49c994c..a84c400fb 100644
--- a/test/plugins/convertPathData.14.svg
+++ b/test/plugins/convertPathData.14.svg
@@ -16,14 +16,10 @@
-
+
-
+
-
-@@@
-
-{"smartArcRounding": false}
\ No newline at end of file
diff --git a/test/plugins/convertPathData.32.svg b/test/plugins/convertPathData.32.svg
index 86d418491..97df96b12 100644
--- a/test/plugins/convertPathData.32.svg
+++ b/test/plugins/convertPathData.32.svg
@@ -2,12 +2,12 @@ Should convert arc to line
===
-