parseArcCommand method
dynamic
parseArcCommand(
- dynamic path,
- dynamic rx,
- dynamic ry,
- dynamic xAxisRotation,
- dynamic largeArcFlag,
- dynamic sweepFlag,
- dynamic start,
- dynamic end,
- https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
- https://mortoray.com/2017/02/16/rendering-an-svg-elliptical-arc-as-bezier-curves/ Appendix: Endpoint to center arc conversion
- From
- rx ry x-axis-rotation large-arc-flag sweep-flag x y
- To
- aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation
- https://mortoray.com/2017/02/16/rendering-an-svg-elliptical-arc-as-bezier-curves/ Appendix: Endpoint to center arc conversion
Implementation
parseArcCommand(
path, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, start, end) {
if (rx == 0 || ry == 0) {
// draw a line if either of the radii == 0
path.lineTo(end.x, end.y);
return;
}
xAxisRotation = xAxisRotation * Math.PI / 180;
// Ensure radii are positive
rx = Math.abs(rx);
ry = Math.abs(ry);
// Compute (x1', y1')
var dx2 = (start.x - end.x) / 2.0;
var dy2 = (start.y - end.y) / 2.0;
var x1p = Math.cos(xAxisRotation) * dx2 + Math.sin(xAxisRotation) * dy2;
var y1p = -Math.sin(xAxisRotation) * dx2 + Math.cos(xAxisRotation) * dy2;
// Compute (cx', cy')
var rxs = rx * rx;
var rys = ry * ry;
var x1ps = x1p * x1p;
var y1ps = y1p * y1p;
// Ensure radii are large enough
var cr = x1ps / rxs + y1ps / rys;
if (cr > 1) {
// scale up rx,ry equally so cr == 1
var s = Math.sqrt(cr);
rx = s * rx;
ry = s * ry;
rxs = rx * rx;
rys = ry * ry;
}
var dq = (rxs * y1ps + rys * x1ps);
var pq = (rxs * rys - dq) / dq;
var q = Math.sqrt(Math.max(0, pq));
if (largeArcFlag == sweepFlag) q = -q;
var cxp = q * rx * y1p / ry;
var cyp = -q * ry * x1p / rx;
// Step 3: Compute (cx, cy) from (cx', cy')
var cx = Math.cos(xAxisRotation) * cxp -
Math.sin(xAxisRotation) * cyp +
(start.x + end.x) / 2;
var cy = Math.sin(xAxisRotation) * cxp +
Math.cos(xAxisRotation) * cyp +
(start.y + end.y) / 2;
// Step 4: Compute θ1 and Δθ
var theta = svgAngle(1, 0, (x1p - cxp) / rx, (y1p - cyp) / ry);
var delta = svgAngle((x1p - cxp) / rx, (y1p - cyp) / ry, (-x1p - cxp) / rx,
(-y1p - cyp) / ry) %
(Math.PI * 2);
path.currentPath.absellipse(
cx, cy, rx, ry, theta, theta + delta, sweepFlag == 0, xAxisRotation);
}