Skip to content
137 changes: 115 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ If you use NPM, `npm install d3-shape`. Otherwise, download the [latest release]


<a name="line_interpolate" href="#line_interpolate">#</a> <i>line</i>.<b>interpolate</b>([<i>interpolate</i>[, <i>t</i>]])
<a name="line_curve" href="#line_curve">#</a> <i>line</i>.<b>curve</b>([<i>curve</i>[, <i>parameters…</i>]])


Expand Down Expand Up @@ -80,39 +80,105 @@ If you use NPM, `npm install d3-shape`. Otherwise, download the [latest release]


<a name="area_interpolate" href="#area_interpolate">#</a> <i>area</i>.<b>interpolate</b>([<i>interpolate</i>[, <i>t</i>]])
<a name="area_curve" href="#area_curve">#</a> <i>area</i>.<b>curve</b>([<i>curve</i>[, <i>parameters…</i>]])


<a name="area_context" href="#area_context">#</a> <i>area</i>.<b>context</b>([<i>context</i>])


### Interpolators
### Curves

Curves are typically not used directly, instead implementing paths for [lines](#lines) and [areas](#areas); they are passed to [*line*.curve](#line_curve) and [*area*.curve](#area_curve).


<a name="curveBasis" href="#curveBasis">#</a> <b>curveBasis</b>(<i>context</i>)


<a name="curveBasisClosed" href="#curveBasisClosed">#</a> <b>curveBasisClosed</b>(<i>context</i>)


<a name="curveBasisOpen" href="#curveBasisOpen">#</a> <b>curveBasisOpen</b>(<i>context</i>)


<a name="curveBundle" href="#curveBundle">#</a> <b>curveBundle</b>(<i>context</i>[, <i>beta</i>])


<a name="curveCardinal" href="#curveCardinal">#</a> <b>curveCardinal</b>(<i>context</i>[, <i>tension</i>])


<a name="curveCardinalClosed" href="#curveCardinalClosed">#</a> <b>curveCardinalClosed</b>(<i>context</i>[, <i>tension</i>])


<a name="curveCardinalOpen" href="#curveCardinalOpen">#</a> <b>curveCardinalOpen</b>(<i>context</i>[, <i>tension</i>])


<a name="curveCatmullRom" href="#curveCatmullRom">#</a> <b>curveCatmullRom</b>(<i>context</i>[, <i>alpha</i>])


<a name="curveCatmullRomClosed" href="#curveCatmullRomClosed">#</a> <b>curveCatmullRomClosed</b>(<i>context</i>[, <i>alpha</i>])


<a name="curveCatmullRomOpen" href="#curveCatmullRomOpen">#</a> <b>curveCatmullRomOpen</b>(<i>context</i>[, <i>alpha</i>])


<a name="curveLinear" href="#curveLinear">#</a> <b>curveLinear</b>(<i>context</i>)


<a name="curveLinearClosed" href="#curveLinearClosed">#</a> <b>curveLinearClosed</b>(<i>context</i>)


<a name="curveNatural" href="#curveNatural">#</a> <b>curveNatural</b>(<i>context</i>)


<a name="curveStep" href="#curveStep">#</a> <b>curveStep</b>(<i>context</i>)


<a name="curveStepAfter" href="#curveStepAfter">#</a> <b>curveStepAfter</b>(<i>context</i>)


<a name="interpolate" href="#interpolate">#</a> <i>interpolate</i>(<i>context</i>)
<a name="curveStepBefore" href="#curveStepBefore">#</a> <b>curveStepBefore</b>(<i>context</i>)


<a name="interpolator_areaStart" href="#interpolator_areaStart">#</a> <i>interpolator</i>.<b>areaStart</b>()
<a name="curve_areaStart" href="#curve_areaStart">#</a> <i>curve</i>.<b>areaStart</b>()


<a name="interpolator_areaEnd" href="#interpolator_areaEnd">#</a> <i>interpolator</i>.<b>areaEnd</b>()
Note: not implemented by closed curves, such as <a href="#curveLinearClosed">curveLinearClosed</a>.

<a name="curve_areaEnd" href="#curve_areaEnd">#</a> <i>curve</i>.<b>areaEnd</b>()


<a name="interpolator_lineStart" href="#interpolator_lineStart">#</a> <i>interpolator</i>.<b>lineStart</b>()
Note: not implemented by closed curves, such as <a href="#curveLinearClosed">curveLinearClosed</a>.

<a name="curve_lineStart" href="#curve_lineStart">#</a> <i>curve</i>.<b>lineStart</b>()


<a name="interpolator_lineEnd" href="#interpolator_lineEnd">#</a> <i>interpolator</i>.<b>lineEnd</b>()
<a name="curve_lineEnd" href="#curve_lineEnd">#</a> <i>curve</i>.<b>lineEnd</b>()


<a name="interpolator_point" href="#interpolator_point">#</a> <i>interpolator</i>.<b>point</b>(<i>x</i>, <i>y</i>)
<a name="curve_point" href="#curve_point">#</a> <i>curve</i>.<b>point</b>(<i>x</i>, <i>y</i>)


Expand All @@ -136,30 +202,57 @@ If you use NPM, `npm install d3-shape`. Otherwise, download the [latest release]


### Symbol Types

Symbol types are typically not used directly, instead implementing paths for [symbols](#symbols); they are passed to [*symbol*.type](#symbol_type).


<a name="symbolTypes" href="#symbolTypes">#</a> <b>symbolTypes</b>

An array containing the set of supported [symbol types](#symbol_type):
An array containing the set of all built-in symbol types: [circle](#symbolCircle), [cross](#symbolCross), [diamond](#symbolDiamond), [square](#symbolSquare), [downwards triangle](#symbolTriangleDown), and [upwards triangle](#symbolTriangleUp). Useful for constructing the range of an [ordinal scale](https://github.com/d3/d3-scale#ordinal-scales) should you wish to use a shape encoding for categorical data.

<a name="symbolCircle" href="#symbolCircle">#</a> <b>symbolCircle</b>


<a name="symbolCross" href="#symbolCross">#</a> <b>symbolCross</b>


<a name="symbolDiamond" href="#symbolDiamond">#</a> <b>symbolDiamond</b>


<a name="symbolSquare" href="#symbolSquare">#</a> <b>symbolSquare</b>


<a name="symbolTriangleDown" href="#symbolTriangleDown">#</a> <b>symbolTriangleDown</b>


<a name="symbolTriangleUp" href="#symbolTriangleUp">#</a> <b>symbolTriangleUp</b>

* `circle`
* `cross`
* `diamond`
* `square`
* `triangle-down`
* `triangle-up`

<a name="symbolType_draw" href="#symbolType_draw">#</a> <i>symbolType</i>.<b>draw</b>(<i>context</i>, <i>size</i>)


## Changes from D3 3.x:

* You can now render shapes to Canvas by specifying a context (e.g., [*line*.context](#line_context))!
* You can now render shapes to Canvas by specifying a context (e.g., [*line*.context](#line_context))! See [d3-path](https://github.com/d3/d3-path) for how it works.

* The interpretation of the Cardinal spline tension parameter has been fixed. The default tension is now 0 (corresponding to a uniform Catmull–Rom spline), not 0.7. Due to a bug in 3.x, the tension parameter was previously only valid in the range [2/3, 1]; this corresponds to the new corrected range of [0, 1]. Thus, the new default value of 0 is equivalent to the old value of 2/3, and the default behavior is only slightly changed.
* The interpretation of the [cardinal](#cardinal) spline tension parameter has been fixed. The default tension is now 0 (corresponding to a uniform Catmull–Rom spline), not 0.7. Due to a bug in 3.x, the tension parameter was previously only valid in the range [2/3, 1]; this corresponds to the new corrected range of [0, 1]. Thus, the new default value of 0 is equivalent to the old value of 2/3, and the default behavior is only slightly changed.

* To specify a Cardinal interpolation tension of *t*, use `line.interpolate("cardinal", t)` instead of `line.interpolate("cardinal").tension(t)`.
* To specify a [cardinal](#curveCardinal) spline tension of *t*, use `line.curve(curveCardinal, t)` instead of `line.interpolate("cardinal").tension(t)`.

* The custom interpolator API has changed.
* To specify a custom line or area interpolator, implement a [curve](#curves).

* Added natural cubic spline interpolation.
* Added [natural](#curveNatural) cubic splines.

* Added “catmull-rom” spline interpolation, parameterized by alpha. If α = 0, produces a uniform Catmull–Rom spline equivalent to a Cardinal spline with zero tension; if α = 0.5, produces a centripetal spline; if α = 1.0, produces a chordal spline.
* Added [Catmull–Rom](#curveCatmullRom) splines, parameterized by alpha. If α = 0, produces a uniform Catmull–Rom spline equivalent to a Cardinal spline with zero tension; if α = 0.5, produces a centripetal spline; if α = 1.0, produces a chordal spline.

* By setting [*area*.x1](#area_x1) or [*area*.y1](#area_y1) to null, you can reuse the [*area*.x0](#area_x0) or [*area*.y0](#area_y0) value, rather than computing it twice. This is useful for nondeterministic values (e.g., jitter).

Expand Down
24 changes: 24 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
export {default as area} from "./src/area";
export {default as line} from "./src/line";

export {default as curveBasisClosed} from "./src/curve/basis-closed";
export {default as curveBasisOpen} from "./src/curve/basis-open";
export {default as curveBasis} from "./src/curve/basis";
export {default as curveBundle} from "./src/curve/bundle";
export {default as curveCardinalClosed} from "./src/curve/cardinal-closed";
export {default as curveCardinalOpen} from "./src/curve/cardinal-open";
export {default as curveCardinal} from "./src/curve/cardinal";
export {default as curveCatmullRomClosed} from "./src/curve/catmull-rom-closed";
export {default as curveCatmullRomOpen} from "./src/curve/catmull-rom-open";
export {default as curveCatmullRom} from "./src/curve/catmull-rom";
export {default as curveLinearClosed} from "./src/curve/linear-closed";
export {default as curveLinear} from "./src/curve/linear";
export {default as curveNatural} from "./src/curve/natural";
export {default as curveStepAfter} from "./src/curve/step-after";
export {default as curveStepBefore} from "./src/curve/step-before";
export {default as curveStep} from "./src/curve/step";

export {default as symbol, symbolTypes} from "./src/symbol";

export {default as symbolCircle} from "./src/symbol/circle";
export {default as symbolCross} from "./src/symbol/cross";
export {default as symbolDiamond} from "./src/symbol/diamond";
export {default as symbolSquare} from "./src/symbol/square";
export {triangleDown as symbolTriangleDown, triangleUp as symbolTriangleUp} from "./src/symbol/triangle";
66 changes: 21 additions & 45 deletions src/area.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,18 @@
import {path} from "d3-path";
import basis from "./interpolate/basis";
import basisOpen from "./interpolate/basis-open";
import cardinal from "./interpolate/cardinal";
import cardinalOpen from "./interpolate/cardinal-open";
import catmullRom from "./interpolate/catmull-rom";
import catmullRomOpen from "./interpolate/catmull-rom-open";
import constant, {constantTrue, constantZero} from "./constant";
import linear from "./interpolate/linear";
import natural from "./interpolate/natural";
import step from "./interpolate/step";
import stepAfter from "./interpolate/step-after";
import stepBefore from "./interpolate/step-before";
import constant from "./constant";
import curveLinear from "./curve/linear";
import curveCurry from "./curve/curry";
import {x as pointX, y as pointY} from "./point";

export default function() {
var x0 = pointX,
x1 = null,
y0 = constantZero,
y0 = constant(0),
y1 = pointY,
defined = constantTrue,
defined = constant(true),
context = null,
interpolate = linear,
interpolator = null;
curve = curveLinear,
output = null;

function area(data) {
var i,
Expand All @@ -34,31 +25,31 @@ export default function() {
x0z = new Array(n),
y0z = new Array(n);

if (!context) interpolator = interpolate(buffer = path());
if (!context) output = curve(buffer = path());

for (i = 0; i <= n; ++i) {
if (!(i < n && defined(d = data[i], i)) === defined0) {
if (defined0 = !defined0) {
j = i;
interpolator.areaStart();
interpolator.lineStart();
output.areaStart();
output.lineStart();
} else {
interpolator.lineEnd();
interpolator.lineStart();
output.lineEnd();
output.lineStart();
for (k = i - 1; k >= j; --k) {
interpolator.point(x0z[k], y0z[k]);
output.point(x0z[k], y0z[k]);
}
interpolator.lineEnd();
interpolator.areaEnd();
output.lineEnd();
output.areaEnd();
}
}
if (defined0) {
x0z[i] = +x0(d, i), y0z[i] = +y0(d, i);
interpolator.point(x1 ? +x1(d, i) : x0z[i], y1 ? +y1(d, i) : y0z[i]);
output.point(x1 ? +x1(d, i) : x0z[i], y1 ? +y1(d, i) : y0z[i]);
}
}

if (buffer) return interpolator = null, buffer + "" || null;
if (buffer) return output = null, buffer + "" || null;
}

area.x = function(_) {
Expand Down Expand Up @@ -89,28 +80,13 @@ export default function() {
return arguments.length ? (defined = typeof _ === "function" ? _ : constant(!!_), area) : defined;
};

area.interpolate = function(_, a) {
if (!arguments.length) return interpolate;
if (typeof _ === "function") interpolate = _;
else switch (_ + "") {
case "step": interpolate = step; break;
case "step-before": interpolate = stepBefore; break;
case "step-after": interpolate = stepAfter; break;
case "basis": interpolate = basis; break;
case "basis-open": interpolate = basisOpen; break;
case "cardinal": interpolate = cardinal(a); break;
case "cardinal-open": interpolate = cardinalOpen(a); break;
case "catmull-rom": interpolate = catmullRom(a); break;
case "catmull-rom-open": interpolate = catmullRomOpen(a); break;
case "natural": interpolate = natural; break;
default: interpolate = linear; break;
}
if (context != null) interpolator = interpolate(context);
return area;
area.curve = function(_) {
var n = arguments.length;
return n ? (curve = n > 1 ? curveCurry(_, arguments) : _, context != null && (output = curve(context)), area) : curve;
};

area.context = function(_) {
return arguments.length ? (_ == null ? context = interpolator = null : interpolator = interpolate(context = _), area) : context;
return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context;
};

return area;
Expand Down
8 changes: 0 additions & 8 deletions src/constant.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,3 @@ export default function(x) {
return x;
};
};

export function constantTrue() {
return true;
};

export function constantZero() {
return 0;
};
File renamed without changes.
File renamed without changes.
File renamed without changes.
8 changes: 4 additions & 4 deletions src/interpolate/bundle.js → src/curve/bundle.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import basis from "./basis";
import linear from "./linear";

function bundle(beta) {
return beta == null || (beta = +beta) === 1 ? basis
: function(context) { return new Bundle(context, beta); };
function bundle(context, beta) {
return beta == null || (beta = +beta) === 1
? basis(context)
: new Bundle(context, beta);
}

function Bundle(context, beta) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import {point} from "./cardinal";

function cardinalClosed(tension) {
var k = (tension == null ? 1 : 1 - tension) / 6;
return function(context) {
return new CardinalClosed(context, k);
};
function cardinalClosed(context, tension) {
return new CardinalClosed(context, (tension == null ? 1 : 1 - tension) / 6);
}

function CardinalClosed(context, k) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import {point} from "./cardinal";

function cardinalOpen(tension) {
var k = (tension == null ? 1 : 1 - tension) / 6;
return function(context) {
return new CardinalOpen(context, k);
};
function cardinalOpen(context, tension) {
return new CardinalOpen(context, (tension == null ? 1 : 1 - tension) / 6);
}

function CardinalOpen(context, k) {
Expand Down
7 changes: 2 additions & 5 deletions src/interpolate/cardinal.js → src/curve/cardinal.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,8 @@ export function point(that, x, y) {
);
};

function cardinal(tension) {
var k = (tension == null ? 1 : 1 - tension) / 6;
return function(context) {
return new Cardinal(context, k);
};
function cardinal(context, tension) {
return new Cardinal(context, (tension == null ? 1 : 1 - tension) / 6);
}

function Cardinal(context, k) {
Expand Down
Loading