UNPKG

@visactor/vrender-core

Version:
54 lines (45 loc) 3.61 kB
"use strict"; 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