@visactor/vrender-core
Version:
## Description
54 lines (45 loc) • 3.61 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.addArcToBezierPath = exports.drawArc = exports.bezier = exports.segments = void 0;
const vutils_1 = require("@visactor/vutils");
function segments(x, y, rx, ry, large, sweep, rotateX, ox, oy) {
const th = (0, vutils_1.degreeToRadian)(rotateX), sin_th = Math.sin(th), cos_th = Math.cos(th), px = cos_th * (ox - x) * .5 + sin_th * (oy - y) * .5, py = cos_th * (oy - y) * .5 - sin_th * (ox - x) * .5;
let pl = px * px / ((rx = Math.abs(rx)) * rx) + py * py / ((ry = Math.abs(ry)) * ry);
pl > 1 && (pl = Math.sqrt(pl), rx *= pl, ry *= pl);
const a00 = cos_th / rx, a01 = sin_th / rx, a10 = -sin_th / ry, a11 = cos_th / ry, x0 = a00 * ox + a01 * oy, y0 = a10 * ox + a11 * oy, x1 = a00 * x + a01 * y, y1 = a10 * x + a11 * y;
let sfactor_sq = 1 / ((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)) - .25;
sfactor_sq < 0 && (sfactor_sq = 0);
let sfactor = Math.sqrt(sfactor_sq);
sweep === large && (sfactor = -sfactor);
const xc = .5 * (x0 + x1) - sfactor * (y1 - y0), yc = .5 * (y0 + y1) + sfactor * (x1 - x0), th0 = Math.atan2(y0 - yc, x0 - xc);
let th_arc = Math.atan2(y1 - yc, x1 - xc) - th0;
th_arc < 0 && 1 === sweep ? th_arc += vutils_1.tau : th_arc > 0 && 0 === sweep && (th_arc -= vutils_1.tau);
const segs = Math.ceil(Math.abs(th_arc / (vutils_1.halfPi + .001))), result = [];
for (let i = 0; i < segs; ++i) {
const th2 = th0 + i * th_arc / segs, th3 = th0 + (i + 1) * th_arc / segs;
result[i] = [ xc, yc, th2, th3, rx, ry, sin_th, cos_th ];
}
return result;
}
function bezier(params) {
const cx = params[0], cy = params[1], th0 = params[2], th1 = params[3], rx = params[4], ry = params[5], sin_th = params[6], cos_th = params[7], a00 = cos_th * rx, a01 = -sin_th * ry, a10 = sin_th * rx, a11 = cos_th * ry, cos_th0 = Math.cos(th0), sin_th0 = Math.sin(th0), cos_th1 = Math.cos(th1), sin_th1 = Math.sin(th1), th_half = .5 * (th1 - th0), sin_th_h2 = Math.sin(.5 * th_half), t = 8 / 3 * sin_th_h2 * sin_th_h2 / Math.sin(th_half), x1 = cx + cos_th0 - t * sin_th0, y1 = cy + sin_th0 + t * cos_th0, x3 = cx + cos_th1, y3 = cy + sin_th1, x2 = x3 + t * sin_th1, y2 = y3 - t * cos_th1;
return [ a00 * x1 + a01 * y1, a10 * x1 + a11 * y1, a00 * x2 + a01 * y2, a10 * x2 + a11 * y2, a00 * x3 + a01 * y3, a10 * x3 + a11 * y3 ];
}
function drawArc(context, x, y, coords) {
const seg = segments(coords[5], coords[6], coords[0], coords[1], coords[3], coords[4], coords[2], x, y);
for (let i = 0; i < seg.length; ++i) {
const bez = bezier(seg[i]);
context.bezierCurveTo(bez[0], bez[1], bez[2], bez[3], bez[4], bez[5]);
}
}
exports.segments = segments, exports.bezier = bezier, exports.drawArc = drawArc;
const addArcToBezierPath = (bezierPath, startAngle, endAngle, cx, cy, rx, ry) => {
const delta = Math.abs(endAngle - startAngle), count = delta > .5 * Math.PI ? Math.ceil(2 * delta / Math.PI) : 1, stepAngle = (endAngle - startAngle) / count;
for (let i = 0; i < count; i++) {
const sa = startAngle + stepAngle * i, ea = startAngle + stepAngle * (i + 1), len = 4 * Math.tan(Math.abs(stepAngle) / 4) / 3, dir = ea < sa ? -1 : 1, c1 = Math.cos(sa), s1 = Math.sin(sa), c2 = Math.cos(ea), s2 = Math.sin(ea), x1 = c1 * rx + cx, y1 = s1 * ry + cy, x4 = c2 * rx + cx, y4 = s2 * ry + cy, hx = rx * len * dir, hy = ry * len * dir;
bezierPath.push(x1 - hx * s1, y1 + hy * c1, x4 + hx * s2, y4 - hy * c2, x4, y4);
}
};
exports.addArcToBezierPath = addArcToBezierPath;
//# sourceMappingURL=arc.js.map