(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-path')) : typeof define === 'function' && define.amd ? define('d3-shape', ['exports', 'd3-path'], factory) : factory((global.d3_shape = {}),global.d3_path); }(this, function (exports,d3Path) { 'use strict'; function constant(x) { return function constant() { return x; }; }; var pi = Math.PI; var halfPi = pi / 2; var tau = 2 * pi; function arcInnerRadius(d) { return d.innerRadius; } function arcOuterRadius(d) { return d.outerRadius; } function arcStartAngle(d) { return d.startAngle; } function arcEndAngle(d) { return d.endAngle; } function arcPadAngle(d) { return d && d.padAngle; // Note: optional! } function asin(x) { return x >= 1 ? halfPi : x <= -1 ? -halfPi : Math.asin(x); } function intersect(x0, y0, x1, y1, x2, y2, x3, y3) { var x10 = x1 - x0, y10 = y1 - y0, x32 = x3 - x2, y32 = y3 - y2, t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / (y32 * x10 - x32 * y10); return [x0 + t * x10, y0 + t * y10]; } // Compute perpendicular offset line of length rc. // http://mathworld.wolfram.com/Circle-LineIntersection.html function cornerTangents(x0, y0, x1, y1, r1, rc, cw) { var x01 = x0 - x1, y01 = y0 - y1, lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), ox = lo * y01, oy = -lo * x01, x11 = x0 + ox, y11 = y0 + oy, x10 = x1 + ox, y10 = y1 + oy, x00 = (x11 + x10) / 2, y00 = (y11 + y10) / 2, dx = x10 - x11, dy = y10 - y11, d2 = dx * dx + dy * dy, r = r1 - rc, D = x11 * y10 - x10 * y11, d = (dy < 0 ? -1 : 1) * Math.sqrt(Math.max(0, r * r * d2 - D * D)), cx0 = (D * dy - dx * d) / d2, cy0 = (-D * dx - dy * d) / d2, cx1 = (D * dy + dx * d) / d2, cy1 = (-D * dx + dy * d) / d2, dx0 = cx0 - x00, dy0 = cy0 - y00, dx1 = cx1 - x00, dy1 = cy1 - y00; // Pick the closer of the two intersection points. // TODO Is there a faster way to determine which intersection to use? if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; return { cx: cx0, cy: cy0, x01: -ox, y01: -oy, x11: cx0 * (r1 / r - 1), y11: cy0 * (r1 / r - 1) }; } function arc() { var innerRadius = arcInnerRadius, outerRadius = arcOuterRadius, cornerRadius = constant(0), padRadius = null, startAngle = arcStartAngle, endAngle = arcEndAngle, padAngle = arcPadAngle, context = null, output = null; function arc() { var buffer, r, r0 = +innerRadius.apply(this, arguments), r1 = +outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) - halfPi, a1 = endAngle.apply(this, arguments) - halfPi, da = Math.abs(a1 - a0), cw = a1 > a0; if (!context) context = buffer = d3Path.path(); // Ensure that the outer radius is always larger than the inner radius. if (r1 < r0) r = r1, r1 = r0, r0 = r; // Is it a point? if (!(r1 > 0)) context.moveTo(0, 0); // Or is it a circle or annulus? else if (da >= tau) { context.moveTo(r1 * Math.cos(a0), r1 * Math.sin(a0)); context.arc(0, 0, r1, a0, a1, !cw); if (r0 > 0) { context.moveTo(r0 * Math.cos(a1), r0 * Math.sin(a1)); context.arc(0, 0, r0, a1, a0, cw); } } // Or is it a circular or annular sector? else { var a01 = a0, a11 = a1, a00 = a0, a10 = a1, da0 = da, da1 = da, ap = padAngle.apply(this, arguments) / 2, rp = (ap > 0) && (padRadius ? +padRadius.apply(this, arguments) : Math.sqrt(r0 * r0 + r1 * r1)), rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)), rc0 = rc, rc1 = rc; // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0. if (rp > 0) { var p0 = asin(rp / r0 * Math.sin(ap)), p1 = asin(rp / r1 * Math.sin(ap)); if ((da0 -= p0 * 2) > 0) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0; else da0 = 0, a00 = a10 = (a0 + a1) / 2; if ((da1 -= p1 * 2) > 0) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1; else da1 = 0, a01 = a11 = (a0 + a1) / 2; } var x01 = r1 * Math.cos(a01), y01 = r1 * Math.sin(a01), x10 = r0 * Math.cos(a10), y10 = r0 * Math.sin(a10); // Apply rounded corners? if (rc > 0) { var x11 = r1 * Math.cos(a11), y11 = r1 * Math.sin(a11), x00 = r0 * Math.cos(a00), y00 = r0 * Math.sin(a00); // Restrict the corner radius according to the sector angle. if (da < pi) { var oc = da0 > 0 ? intersect(x01, y01, x00, y00, x11, y11, x10, y10) : [x10, y10], ax = x01 - oc[0], ay = y01 - oc[1], bx = x11 - oc[0], by = y11 - oc[1], kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2), lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]); rc0 = Math.min(rc, (r0 - lc) / (kc - 1)); rc1 = Math.min(rc, (r1 - lc) / (kc + 1)); } } // Is the sector collapsed to a line? if (!(da1 > 0)) context.moveTo(x01, y01); // Does the sector’s outer ring have rounded corners? else if (rc1 > 0) { var t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw), t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw); context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01); // Have the corners merged? if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw); // Otherwise, draw the two corners and the ring. else { context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw); context.arc(0, 0, r1, Math.atan2(t0.cy + t0.y11, t0.cx + t0.x11), Math.atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw); context.arc(t1.cx, t1.cy, rc1, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw); } } // Or is the outer ring just a circular arc? else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw); // Is there no inner ring, and it’s a circular sector? // Or perhaps it’s an annular sector collapsed due to padding? if (!(r0 > 0) || !(da0 > 0)) context.lineTo(x10, y10); // Does the sector’s inner ring (or point) have rounded corners? else if (rc0 > 0) { var t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw), t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw); context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01); // Have the corners merged? if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw); // Otherwise, draw the two corners and the ring. else { context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw); context.arc(0, 0, r0, Math.atan2(t0.cy + t0.y11, t0.cx + t0.x11), Math.atan2(t1.cy + t1.y11, t1.cx + t1.x11), cw); context.arc(t1.cx, t1.cy, rc0, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw); } } // Or is the inner ring just a circular arc? else context.arc(0, 0, r0, a10, a00, cw); } context.closePath(); if (buffer) return context = null, buffer + "" || null; } arc.centroid = function() { var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi / 2; return [Math.cos(a) * r, Math.sin(a) * r]; }; arc.innerRadius = function(_) { return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant(+_), arc) : innerRadius; }; arc.outerRadius = function(_) { return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant(+_), arc) : outerRadius; }; arc.cornerRadius = function(_) { return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant(+_), arc) : cornerRadius; }; arc.padRadius = function(_) { return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant(+_), arc) : padRadius; }; arc.startAngle = function(_) { return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant(+_), arc) : startAngle; }; arc.endAngle = function(_) { return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant(+_), arc) : endAngle; }; arc.padAngle = function(_) { return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant(+_), arc) : padAngle; }; arc.context = function(_) { return arguments.length ? ((context = output = _ == null ? null : _), arc) : context; }; return arc; }; var slice = Array.prototype.slice; function bind(curve, args) { if (args.length < 2) return curve; args = slice.call(args); args[0] = null; return function(context) { args[0] = context; return curve.apply(null, args); }; }; function Linear(context) { this._context = context; } Linear.prototype = { areaStart: function() { this._line = 0; }, areaEnd: function() { this._line = NaN; }, lineStart: function() { this._point = 0; }, lineEnd: function() { if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); this._line = 1 - this._line; }, point: function(x, y) { x = +x, y = +y; switch (this._point) { case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; case 1: this._point = 2; // proceed default: this._context.lineTo(x, y); break; } } }; function curveLinear(context) { return new Linear(context); }; function x(p) { return p[0]; }; function y(p) { return p[1]; }; function area() { var x0 = x, x1 = null, y0 = constant(0), y1 = y, defined = constant(true), context = null, curve = curveLinear, output = null; function area(data) { var i, j, k, n = data.length, d, defined0 = false, buffer, x0z = new Array(n), y0z = new Array(n); if (!context) output = curve(buffer = d3Path.path()); for (i = 0; i <= n; ++i) { if (!(i < n && defined(d = data[i], i, data)) === defined0) { if (defined0 = !defined0) { j = i; output.areaStart(); output.lineStart(); } else { output.lineEnd(); output.lineStart(); for (k = i - 1; k >= j; --k) { output.point(x0z[k], y0z[k]); } output.lineEnd(); output.areaEnd(); } } if (defined0) { x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data); output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]); } } if (buffer) return output = null, buffer + "" || null; } area.x = function(_) { return arguments.length ? (x0 = typeof _ === "function" ? _ : constant(+_), x1 = null, area) : x0; }; area.x0 = function(_) { return arguments.length ? (x0 = typeof _ === "function" ? _ : constant(+_), area) : x0; }; area.x1 = function(_) { return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant(+_), area) : x1; }; area.y = function(_) { return arguments.length ? (y0 = typeof _ === "function" ? _ : constant(+_), y1 = null, area) : y0; }; area.y0 = function(_) { return arguments.length ? (y0 = typeof _ === "function" ? _ : constant(+_), area) : y0; }; area.y1 = function(_) { return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant(+_), area) : y1; }; area.defined = function(_) { return arguments.length ? (defined = typeof _ === "function" ? _ : constant(!!_), area) : defined; }; area.curve = function(_) { return arguments.length ? (curve = bind(_, arguments), context != null && (output = curve(context)), area) : curve; }; area.context = function(_) { return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context; }; return area; }; function noop() {}; function point(that, x, y) { that._context.bezierCurveTo( (2 * that._x0 + that._x1) / 3, (2 * that._y0 + that._y1) / 3, (that._x0 + 2 * that._x1) / 3, (that._y0 + 2 * that._y1) / 3, (that._x0 + 4 * that._x1 + x) / 6, (that._y0 + 4 * that._y1 + y) / 6 ); }; function Basis(context) { this._context = context; } Basis.prototype = { areaStart: function() { this._line = 0; }, areaEnd: function() { this._line = NaN; }, lineStart: function() { this._x0 = this._x1 = this._y0 = this._y1 = NaN; this._point = 0; }, lineEnd: function() { switch (this._point) { case 3: point(this, this._x1, this._y1); // proceed case 2: this._context.lineTo(this._x1, this._y1); break; } if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); this._line = 1 - this._line; }, point: function(x, y) { x = +x, y = +y; switch (this._point) { case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; case 1: this._point = 2; break; case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed default: point(this, x, y); break; } this._x0 = this._x1, this._x1 = x; this._y0 = this._y1, this._y1 = y; } }; function basis(context) { return new Basis(context); }; function BasisClosed(context) { this._context = context; } BasisClosed.prototype = { areaStart: noop, areaEnd: noop, lineStart: function() { this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN; this._point = 0; }, lineEnd: function() { switch (this._point) { case 1: { this._context.moveTo(this._x2, this._y2); this._context.closePath(); break; } case 2: { this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3); this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3); this._context.closePath(); break; } case 3: { this.point(this._x2, this._y2); this.point(this._x3, this._y3); this.point(this._x4, this._y4); break; } } }, point: function(x, y) { x = +x, y = +y; switch (this._point) { case 0: this._point = 1; this._x2 = x, this._y2 = y; break; case 1: this._point = 2; this._x3 = x, this._y3 = y; break; case 2: this._point = 3; this._x4 = x, this._y4 = y; this._context.moveTo((this._x0 + 4 * this._x1 + x) / 6, (this._y0 + 4 * this._y1 + y) / 6); break; default: point(this, x, y); break; } this._x0 = this._x1, this._x1 = x; this._y0 = this._y1, this._y1 = y; } }; function basisClosed(context) { return new BasisClosed(context); }; function BasisOpen(context) { this._context = context; } BasisOpen.prototype = { areaStart: function() { this._line = 0; }, areaEnd: function() { this._line = NaN; }, lineStart: function() { this._x0 = this._x1 = this._y0 = this._y1 = NaN; this._point = 0; }, lineEnd: function() { if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); this._line = 1 - this._line; }, point: function(x, y) { x = +x, y = +y; switch (this._point) { case 0: this._point = 1; break; case 1: this._point = 2; break; case 2: this._point = 3; var x0 = (this._x0 + 4 * this._x1 + x) / 6, y0 = (this._y0 + 4 * this._y1 + y) / 6; this._line ? this._context.lineTo(x0, y0) : this._context.moveTo(x0, y0); break; case 3: this._point = 4; // proceed default: point(this, x, y); break; } this._x0 = this._x1, this._x1 = x; this._y0 = this._y1, this._y1 = y; } }; function basisOpen(context) { return new BasisOpen(context); }; function Bundle(context, beta) { this._basis = basis(context); this._beta = beta; } Bundle.prototype = { lineStart: function() { this._x = []; this._y = []; this._basis.lineStart(); }, lineEnd: function() { var x = this._x, y = this._y, j = x.length - 1; if (j > 0) { var x0 = x[0], y0 = y[0], dx = x[j] - x0, dy = y[j] - y0, i = -1, t; while (++i <= j) { t = i / j; this._basis.point( this._beta * x[i] + (1 - this._beta) * (x0 + t * dx), this._beta * y[i] + (1 - this._beta) * (y0 + t * dy) ); } } this._x = this._y = null; this._basis.lineEnd(); }, point: function(x, y) { this._x.push(+x); this._y.push(+y); } }; function bundle(context, beta) { return beta == null ? new Bundle(context, 0.85) : (beta = +beta) === 1 ? basis(context) : new Bundle(context, beta); }; function point$1(that, x, y) { that._context.bezierCurveTo( that._x1 + that._k * (that._x2 - that._x0), that._y1 + that._k * (that._y2 - that._y0), that._x2 + that._k * (that._x1 - x), that._y2 + that._k * (that._y1 - y), that._x2, that._y2 ); }; function Cardinal(context, k) { this._context = context; this._k = k; } Cardinal.prototype = { areaStart: function() { this._line = 0; }, areaEnd: function() { this._line = NaN; }, lineStart: function() { this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN; this._point = 0; }, lineEnd: function() { switch (this._point) { case 2: this._context.lineTo(this._x2, this._y2); break; case 3: point$1(this, this._x1, this._y1); break; } if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); this._line = 1 - this._line; }, point: function(x, y) { x = +x, y = +y; switch (this._point) { case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; case 1: this._point = 2; this._x1 = x, this._y1 = y; break; case 2: this._point = 3; // proceed default: point$1(this, x, y); break; } this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; } }; function cardinal(context, tension) { return new Cardinal(context, (tension == null ? 1 : 1 - tension) / 6); }; function CardinalClosed(context, k) { this._context = context; this._k = k; } CardinalClosed.prototype = { areaStart: noop, areaEnd: noop, lineStart: function() { this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; this._point = 0; }, lineEnd: function() { switch (this._point) { case 1: { this._context.moveTo(this._x3, this._y3); this._context.closePath(); break; } case 2: { this._context.lineTo(this._x3, this._y3); this._context.closePath(); break; } case 3: { this.point(this._x3, this._y3); this.point(this._x4, this._y4); this.point(this._x5, this._y5); break; } } }, point: function(x, y) { x = +x, y = +y; switch (this._point) { case 0: this._point = 1; this._x3 = x, this._y3 = y; break; case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; case 2: this._point = 3; this._x5 = x, this._y5 = y; break; default: point$1(this, x, y); break; } this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; } }; function cardinalClosed(context, tension) { return new CardinalClosed(context, (tension == null ? 1 : 1 - tension) / 6); }; function CardinalOpen(context, k) { this._context = context; this._k = k; } CardinalOpen.prototype = { areaStart: function() { this._line = 0; }, areaEnd: function() { this._line = NaN; }, lineStart: function() { this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN; this._point = 0; }, lineEnd: function() { if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); this._line = 1 - this._line; }, point: function(x, y) { x = +x, y = +y; switch (this._point) { case 0: this._point = 1; break; case 1: this._point = 2; break; case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; case 3: this._point = 4; // proceed default: point$1(this, x, y); break; } this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; } }; function cardinalOpen(context, tension) { return new CardinalOpen(context, (tension == null ? 1 : 1 - tension) / 6); }; var epsilon = 1e-6; function point$2(that, x, y) { var x1 = that._x1, y1 = that._y1, x2 = that._x2, y2 = that._y2; if (that._l01_a > epsilon) { var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a, n = 3 * that._l01_a * (that._l01_a + that._l12_a); x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n; y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n; } if (that._l23_a > epsilon) { var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a, m = 3 * that._l23_a * (that._l23_a + that._l12_a); x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m; y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m; } that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2); }; function CatmullRom(context, alpha) { this._context = context; this._alpha = alpha; } CatmullRom.prototype = { areaStart: function() { this._line = 0; }, areaEnd: function() { this._line = NaN; }, lineStart: function() { this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN; this._l01_a = this._l12_a = this._l23_a = this._l01_2a = this._l12_2a = this._l23_2a = this._point = 0; }, lineEnd: function() { switch (this._point) { case 2: this._context.lineTo(this._x2, this._y2); break; case 3: this.point(this, this._x2, this._y2); break; } if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); this._line = 1 - this._line; }, point: function(x, y) { x = +x, y = +y; if (this._point) { var x23 = this._x2 - x, y23 = this._y2 - y; this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); } switch (this._point) { case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; case 1: this._point = 2; break; case 2: this._point = 3; // proceed default: point$2(this, x, y); break; } this._l01_a = this._l12_a, this._l12_a = this._l23_a; this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; } }; function catmullRom(context, alpha) { return (alpha = alpha == null ? 0.5 : +alpha) ? new CatmullRom(context, alpha) : cardinal(context, 0); }; function CatmullRomClosed(context, alpha) { this._context = context; this._alpha = alpha; } CatmullRomClosed.prototype = { areaStart: noop, areaEnd: noop, lineStart: function() { this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; this._l01_a = this._l12_a = this._l23_a = this._l01_2a = this._l12_2a = this._l23_2a = this._point = 0; }, lineEnd: function() { switch (this._point) { case 1: { this._context.moveTo(this._x3, this._y3); this._context.closePath(); break; } case 2: { this._context.lineTo(this._x3, this._y3); this._context.closePath(); break; } case 3: { this.point(this._x3, this._y3); this.point(this._x4, this._y4); this.point(this._x5, this._y5); break; } } }, point: function(x, y) { x = +x, y = +y; if (this._point) { var x23 = this._x2 - x, y23 = this._y2 - y; this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); } switch (this._point) { case 0: this._point = 1; this._x3 = x, this._y3 = y; break; case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; case 2: this._point = 3; this._x5 = x, this._y5 = y; break; default: point$2(this, x, y); break; } this._l01_a = this._l12_a, this._l12_a = this._l23_a; this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; } }; function catmullRomClosed(context, alpha) { return (alpha = alpha == null ? 0.5 : +alpha) ? new CatmullRomClosed(context, alpha) : cardinalClosed(context, 0); }; function CatmullRomOpen(context, alpha) { this._context = context; this._alpha = alpha; } CatmullRomOpen.prototype = { areaStart: function() { this._line = 0; }, areaEnd: function() { this._line = NaN; }, lineStart: function() { this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN; this._l01_a = this._l12_a = this._l23_a = this._l01_2a = this._l12_2a = this._l23_2a = this._point = 0; }, lineEnd: function() { if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); this._line = 1 - this._line; }, point: function(x, y) { x = +x, y = +y; if (this._point) { var x23 = this._x2 - x, y23 = this._y2 - y; this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); } switch (this._point) { case 0: this._point = 1; break; case 1: this._point = 2; break; case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; case 3: this._point = 4; // proceed default: point$2(this, x, y); break; } this._l01_a = this._l12_a, this._l12_a = this._l23_a; this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; } }; function catmullRomOpen(context, alpha) { return (alpha = alpha == null ? 0.5 : +alpha) ? new CatmullRomOpen(context, alpha) : cardinalOpen(context, 0); }; var circle = { draw: function(context, size) { var r = Math.sqrt(size / pi); context.moveTo(r, 0); context.arc(0, 0, r, 0, tau); } }; var cross = { draw: function(context, size) { var r = Math.sqrt(size / 5) / 2; context.moveTo(-3 * r, -r); context.lineTo(-r, -r); context.lineTo(-r, -3 * r); context.lineTo(r, -3 * r); context.lineTo(r, -r); context.lineTo(3 * r, -r); context.lineTo(3 * r, r); context.lineTo(r, r); context.lineTo(r, 3 * r); context.lineTo(-r, 3 * r); context.lineTo(-r, r); context.lineTo(-3 * r, r); context.closePath(); } }; var tan30 = Math.sqrt(1 / 3); var tan30_2 = tan30 * 2; var diamond = { draw: function(context, size) { var y = Math.sqrt(size / tan30_2), x = y * tan30; context.moveTo(0, -y); context.lineTo(x, 0); context.lineTo(0, y); context.lineTo(-x, 0); context.closePath(); } }; function LinearClosed(context) { this._context = context; } LinearClosed.prototype = { areaStart: noop, areaEnd: noop, lineStart: function() { this._point = 0; }, lineEnd: function() { if (this._point) this._context.closePath(); }, point: function(x, y) { x = +x, y = +y; if (this._point) this._context.lineTo(x, y); else this._point = 1, this._context.moveTo(x, y); } }; function linearClosed(context) { return new LinearClosed(context); }; function line() { var x$$ = x, y$$ = y, defined = constant(true), context = null, curve = curveLinear, output = null; function line(data) { var i, n = data.length, d, defined0 = false, buffer; if (!context) output = curve(buffer = d3Path.path()); for (i = 0; i <= n; ++i) { if (!(i < n && defined(d = data[i], i, data)) === defined0) { if (defined0 = !defined0) output.lineStart(); else output.lineEnd(); } if (defined0) output.point(+x$$(d, i, data), +y$$(d, i, data)); } if (buffer) return output = null, buffer + "" || null; } line.x = function(_) { return arguments.length ? (x$$ = typeof _ === "function" ? _ : constant(+_), line) : x$$; }; line.y = function(_) { return arguments.length ? (y$$ = typeof _ === "function" ? _ : constant(+_), line) : y$$; }; line.defined = function(_) { return arguments.length ? (defined = typeof _ === "function" ? _ : constant(!!_), line) : defined; }; line.curve = function(_) { return arguments.length ? (curve = bind(_, arguments), context != null && (output = curve(context)), line) : curve; }; line.context = function(_) { return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context; }; return line; }; function sign(x) { return x < 0 ? -1 : 1; } // Calculate the slopes of the tangents (Hermite-type interpolation) based on // the following paper: Steffen, M. 1990. A Simple Method for Monotonic // Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO. // NOV(II), P. 443, 1990. function slope3(that, x2, y2) { var h0 = that._x1 - that._x0, h1 = x2 - that._x1, s0 = (that._y1 - that._y0) / h0, s1 = (y2 - that._y1) / h1, p = (s0 * h1 + s1 * h0) / (h0 + h1); return (sign(s0) + sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0; } // Calculate a one-sided slope. function slope2(that, t) { var h = that._x1 - that._x0; return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t; } // According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations // "you can express cubic Hermite interpolation in terms of cubic Bézier curves // with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1". function point$3(that, t0, t1) { var x0 = that._x0, y0 = that._y0, x1 = that._x1, y1 = that._y1, dx = (x1 - x0) / 3; that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1); } function Monotone(context) { this._context = context; } Monotone.prototype = { areaStart: function() { this._line = 0; }, areaEnd: function() { this._line = NaN; }, lineStart: function() { this._x0 = this._x1 = this._y0 = this._y1 = this._t0 = NaN; this._point = 0; }, lineEnd: function() { switch (this._point) { case 2: this._context.lineTo(this._x1, this._y1); break; case 3: point$3(this, this._t0, slope2(this, this._t0)); break; } if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); this._line = 1 - this._line; }, point: function(x, y) { var t1 = NaN; x = +x, y = +y; if (x === this._x1 && y === this._y1) return; // Ignore coincident points. switch (this._point) { case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; case 1: this._point = 2; break; case 2: this._point = 3; point$3(this, slope2(this, t1 = slope3(this, x, y)), t1); break; default: point$3(this, this._t0, t1 = slope3(this, x, y)); break; } this._x0 = this._x1, this._x1 = x; this._y0 = this._y1, this._y1 = y; this._t0 = t1; } } function monotone(context) { return new Monotone(context); }; function Natural(context) { this._context = context; } Natural.prototype = { areaStart: function() { this._line = 0; }, areaEnd: function() { this._line = NaN; }, lineStart: function() { this._x = []; this._y = []; }, lineEnd: function() { var x = this._x, y = this._y, n = x.length; if (n) { this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]); if (n === 2) { this._context.lineTo(x[1], y[1]); } else { var px = controlPoints(x), py = controlPoints(y); for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) { this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]); } } } if (this._line || (this._line !== 0 && n === 1)) this._context.closePath(); this._line = 1 - this._line; this._x = this._y = null; }, point: function(x, y) { this._x.push(+x); this._y.push(+y); } }; // See https://www.particleincell.com/2012/bezier-splines/ for derivation. function controlPoints(x) { var i, n = x.length - 1, m, a = new Array(n), b = new Array(n), r = new Array(n); a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1]; for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1]; a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n]; for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1]; a[n - 1] = r[n - 1] / b[n - 1]; for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i]; b[n - 1] = (x[n] + a[n - 1]) / 2; for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1]; return [a, b]; } function natural(context) { return new Natural(context); }; function descending(a, b) { return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; }; function identity(d) { return d; }; function pie() { var value = identity, sortValues = descending, sort = null, startAngle = constant(0), endAngle = constant(tau), padAngle = constant(0); function pie(data) { var n = data.length, sum = 0, index = new Array(n), arcs = new Array(n), a0 = +startAngle.apply(this, arguments), da = Math.min(tau, Math.max(-tau, endAngle.apply(this, arguments) - a0)), a1, p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)), pa = p * (da < 0 ? -1 : 1); for (var i = 0, v; i < n; ++i) { if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) { sum += v; } } // Optionally sort the arcs by previously-computed values or by data. if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); }); else if (sort !== null) index.sort(function(i, j) { return sort(data[i], data[j]); }); // Compute the arcs! They are stored in the original data's order. for (var i = 0, j, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) { j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = { data: data[j], value: v, startAngle: a0, endAngle: a1, padAngle: p }; } return arcs; } pie.value = function(_) { return arguments.length ? (value = typeof _ === "function" ? _ : constant(+_), pie) : value; }; pie.sortValues = function(_) { return arguments.length ? (sortValues = _, sort = null, pie) : sortValues; }; pie.sort = function(_) { return arguments.length ? (sort = _, sortValues = null, pie) : sort; }; pie.startAngle = function(_) { return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant(+_), pie) : startAngle; }; pie.endAngle = function(_) { return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant(+_), pie) : endAngle; }; pie.padAngle = function(_) { return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant(+_), pie) : padAngle; }; return pie; }; function Radial(curve) { this._curve = curve; } Radial.prototype = { areaStart: function() { this._curve.areaStart(); }, areaEnd: function() { this._curve.areaEnd(); }, lineStart: function() { this._curve.lineStart(); }, lineEnd: function() { this._curve.lineEnd(); }, point: function(a, r) { a -= halfPi, this._curve.point(r * Math.cos(a), r * Math.sin(a)); } }; function curveRadial(curve, args) { curve = bind(curve, args); function radial(context) { return new Radial(curve(context)); } radial._curve = curve; return radial; }; function radialArea() { var a = area(), c = a.curve; a.angle = a.x, delete a.x; a.startAngle = a.x0, delete a.x0; a.endAngle = a.x1, delete a.x1; a.radius = a.y, delete a.y; a.innerRadius = a.y0, delete a.y0; a.outerRadius = a.y1, delete a.y1; a.curve = function(_) { return arguments.length ? c(curveRadial(_, arguments)) : c()._curve; }; return a.curve(curveLinear); }; function radialLine() { var l = line(), c = l.curve; l.angle = l.x, delete l.x; l.radius = l.y, delete l.y; l.curve = function(_) { return arguments.length ? c(curveRadial(_, arguments)) : c()._curve; }; return l.curve(curveLinear); }; var square = { draw: function(context, size) { var w = Math.sqrt(size), x = -w / 2; context.rect(x, x, w, w); } }; var ka = 0.89081309152928522810; var kr = Math.sin(pi / 10) / Math.sin(7 * pi / 10); var kx = Math.sin(tau / 10) * kr; var ky = -Math.cos(tau / 10) * kr; var star = { draw: function(context, size) { var r = Math.sqrt(size * ka), x = kx * r, y = ky * r; context.moveTo(0, -r); context.lineTo(x, y); for (var i = 1; i < 5; ++i) { var a = tau * i / 5, c = Math.cos(a), s = Math.sin(a); context.lineTo(s * r, -c * r); context.lineTo(c * x - s * y, s * x + c * y); } context.closePath(); } }; function StepAfter(context) { this._context = context; } StepAfter.prototype = { areaStart: function() { this._line = 0; }, areaEnd: function() { this._line = NaN; }, lineStart: function() { this._y = NaN; this._point = 0; }, lineEnd: function() { if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); this._line = 1 - this._line; }, point: function(x, y) { x = +x, y = +y; switch (this._point) { case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; case 1: this._point = 2; // proceed default: { this._context.lineTo(x, this._y); this._context.lineTo(x, y); break; } } this._y = y; } }; function stepAfter(context) { return new StepAfter(context); }; function StepBefore(context) { this._context = context; } StepBefore.prototype = { areaStart: function() { this._line = 0; }, areaEnd: function() { this._line = NaN; }, lineStart: function() { this._x = NaN; this._point = 0; }, lineEnd: function() { if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); this._line = 1 - this._line; }, point: function(x, y) { x = +x, y = +y; switch (this._point) { case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; case 1: this._point = 2; // proceed default: { this._context.lineTo(this._x, y); this._context.lineTo(x, y); break; } } this._x = x; } }; function stepBefore(context) { return new StepBefore(context); }; function Step(context) { this._context = context; } Step.prototype = { areaStart: function() { this._line = 0; }, areaEnd: function() { this._line = NaN; }, lineStart: function() { this._x = this._y = NaN; this._point = 0; }, lineEnd: function() { if (this._point === 2) this._context.lineTo(this._x, this._y); if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); this._line = 1 - this._line; }, point: function(x, y) { x = +x, y = +y; switch (this._point) { case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; case 1: this._point = 2; // proceed default: { var x1 = (this._x + x) / 2; this._context.lineTo(x1, this._y); this._context.lineTo(x1, y); break; } } this._x = x, this._y = y; } }; function step(context) { return new Step(context); }; var c = -0.5; var s = Math.sqrt(3) / 2; var k = 1 / Math.sqrt(12); var a = (k / 2 + 1) * 3; var wye = { draw: function(context, size) { var r = Math.sqrt(size / a), x0 = r / 2, y0 = r * k, x1 = x0, y1 = r * k + r, x2 = -x1, y2 = y1; context.moveTo(x0, y0); context.lineTo(x1, y1); context.lineTo(x2, y2); context.lineTo(c * x0 - s * y0, s * x0 + c * y0); context.lineTo(c * x1 - s * y1, s * x1 + c * y1); context.lineTo(c * x2 - s * y2, s * x2 + c * y2); context.lineTo(c * x0 + s * y0, c * y0 - s * x0); context.lineTo(c * x1 + s * y1, c * y1 - s * x1); context.lineTo(c * x2 + s * y2, c * y2 - s * x2); context.closePath(); } }; var sqrt3 = Math.sqrt(3); var triangle = { draw: function(context, size) { var y = -Math.sqrt(size / (sqrt3 * 3)); context.moveTo(0, y * 2); context.lineTo(-sqrt3 * y, -y); context.lineTo(sqrt3 * y, -y); context.closePath(); } }; var symbols = [ circle, cross, diamond, square, star, triangle, wye ]; function symbol() { var type = constant(circle), size = constant(64), context = null; function symbol() { var buffer; if (!context) context = buffer = d3Path.path(); type.apply(this, arguments).draw(context, +size.apply(this, arguments)); if (buffer) return context = null, buffer + "" || null; } symbol.type = function(_) { return arguments.length ? (type = typeof _ === "function" ? _ : constant(_), symbol) : type; }; symbol.size = function(_) { return arguments.length ? (size = typeof _ === "function" ? _ : constant(+_), symbol) : size; }; symbol.context = function(_) { return arguments.length ? (context = _ == null ? null : _, symbol) : context; }; return symbol; }; var version = "0.2.0"; exports.version = version; exports.arc = arc; exports.area = area; exports.basisClosed = basisClosed; exports.basisOpen = basisOpen; exports.basis = basis; exports.bundle = bundle; exports.cardinalClosed = cardinalClosed; exports.cardinalOpen = cardinalOpen; exports.cardinal = cardinal; exports.catmullRomClosed = catmullRomClosed; exports.catmullRomOpen = catmullRomOpen; exports.catmullRom = catmullRom; exports.circle = circle; exports.cross = cross; exports.diamond = diamond; exports.linearClosed = linearClosed; exports.linear = curveLinear; exports.line = line; exports.monotone = monotone; exports.natural = natural; exports.pie = pie; exports.radialArea = radialArea; exports.radialLine = radialLine; exports.square = square; exports.star = star; exports.stepAfter = stepAfter; exports.stepBefore = stepBefore; exports.step = step; exports.symbol = symbol; exports.symbols = symbols; exports.triangle = triangle; exports.wye = wye; }));