# Curves

Curves turn a discrete (pointwise) representation of a line or area into a continuous shape: curves specify how to interpolate between two-dimensional [*x*, *y*] points.

Curves are typically not constructed or used directly. Instead, one of the built-in curves is being passed to *line*.curve or *area*.curve.

```
const line = d3.line()
.x((d) => x(d.date))
.y((d) => y(d.value))
.curve(d3.curveCatmullRom.alpha(0.5));
```

If desired, you can implement a custom curve. For an example of using a curve directly, see Context to Curve.

*curveBasis*(*context*)

Source · Produces a cubic basis spline using the specified control points. The first and last points are triplicated such that the spline starts at the first point and ends at the last point, and is tangent to the line between the first and second points, and to the line between the penultimate and last points.

*curveBasisClosed*(*context*)

Source · Produces a closed cubic basis spline using the specified control points. When a line segment ends, the first three control points are repeated, producing a closed loop with C2 continuity.

*curveBasisOpen*(*context*)

Source · Produces a cubic basis spline using the specified control points. Unlike basis, the first and last points are not repeated, and thus the curve typically does not intersect these points.

*curveBumpX*(*context*)

Source · Produces a Bézier curve between each pair of points, with horizontal tangents at each point.

*curveBumpY*(*context*)

Source · Produces a Bézier curve between each pair of points, with vertical tangents at each point.

*curveBundle*(*context*)

Source · Produces a straightened cubic basis spline using the specified control points, with the spline straightened according to the curve’s *beta*, which defaults to 0.85. This curve is typically used in hierarchical edge bundling to disambiguate connections, as proposed by Danny Holten in Hierarchical Edge Bundles: Visualization of Adjacency Relations in Hierarchical Data. This curve does not implement *curve*.areaStart and *curve*.areaEnd; it is intended to work with d3.line, not d3.area.

## curveBundle.beta(*beta*)

Source · Returns a bundle curve with the specified *beta* in the range [0, 1], representing the bundle strength. If *beta* equals zero, a straight line between the first and last point is produced; if *beta* equals one, a standard basis spline is produced. For example:

`const line = d3.line().curve(d3.curveBundle.beta(0.5));`

*curveCardinal*(*context*)

Source · Produces a cubic cardinal spline using the specified control points, with one-sided differences used for the first and last piece. The default tension is 0.

*curveCardinalClosed*(*context*)

Source · Produces a closed cubic cardinal spline using the specified control points. When a line segment ends, the first three control points are repeated, producing a closed loop. The default tension is 0.

*curveCardinalOpen*(*context*)

Source · Produces a cubic cardinal spline using the specified control points. Unlike curveCardinal, one-sided differences are not used for the first and last piece, and thus the curve starts at the second point and ends at the penultimate point. The default tension is 0.

## curveCardinal.tension(*tension*)

Source · Returns a cardinal curve with the specified *tension* in the range [0, 1]. The *tension* determines the length of the tangents: a *tension* of one yields all zero tangents, equivalent to curveLinear; a *tension* of zero produces a uniform Catmull–Rom spline. For example:

`const line = d3.line().curve(d3.curveCardinal.tension(0.5));`

*curveCatmullRom*(*context*)

Source · Produces a cubic Catmull–Rom spline using the specified control points and the parameter *alpha*, which defaults to 0.5, as proposed by Yuksel et al. in On the Parameterization of Catmull–Rom Curves, with one-sided differences used for the first and last piece.

*curveCatmullRomClosed*(*context*)

Source · Produces a closed cubic Catmull–Rom spline using the specified control points and the parameter *alpha*, which defaults to 0.5, as proposed by Yuksel et al. When a line segment ends, the first three control points are repeated, producing a closed loop.

*curveCatmullRomOpen*(*context*)

Source · Produces a cubic Catmull–Rom spline using the specified control points and the parameter *alpha*, which defaults to 0.5, as proposed by Yuksel et al. Unlike curveCatmullRom, one-sided differences are not used for the first and last piece, and thus the curve starts at the second point and ends at the penultimate point.

## curveCatmullRom.alpha(*alpha*)

Source · Returns a cubic Catmull–Rom curve with the specified *alpha* in the range [0, 1]. If *alpha* is zero, produces a uniform spline, equivalent to curveCardinal with a tension of zero; if *alpha* is one, produces a chordal spline; if *alpha* is 0.5, produces a centripetal spline. Centripetal splines are recommended to avoid self-intersections and overshoot. For example:

`const line = d3.line().curve(d3.curveCatmullRom.alpha(0.5));`

*curveLinear*(*context*)

Source · Produces a polyline through the specified points.

*curveLinearClosed*(*context*)

Source · Produces a closed polyline through the specified points by repeating the first point when the line segment ends.

*curveMonotoneX*(*context*)

Source · Produces a cubic spline that preserves monotonicity in *y*, assuming monotonicity in *x*, as proposed by Steffen in A simple method for monotonic interpolation in one dimension: “a smooth curve with continuous first-order derivatives that passes through any given set of data points without spurious oscillations. Local extrema can occur only at grid points where they are given by the data, but not in between two adjacent grid points.”

*curveMonotoneY*(*context*)

Source · Produces a cubic spline that preserves monotonicity in *x*, assuming monotonicity in *y*, as proposed by Steffen in A simple method for monotonic interpolation in one dimension: “a smooth curve with continuous first-order derivatives that passes through any given set of data points without spurious oscillations. Local extrema can occur only at grid points where they are given by the data, but not in between two adjacent grid points.”

*curveNatural*(*context*)

Source · Produces a natural cubic spline with the second derivative of the spline set to zero at the endpoints.

*curveStep*(*context*)

Source · Produces a piecewise constant function (a step function) consisting of alternating horizontal and vertical lines. The *y*-value changes at the midpoint of each pair of adjacent *x*-values.

*curveStepAfter*(*context*)

Source · Produces a piecewise constant function (a step function) consisting of alternating horizontal and vertical lines. The *y*-value changes after the *x*-value.

*curveStepBefore*(*context*)

Source · Produces a piecewise constant function (a step function) consisting of alternating horizontal and vertical lines. The *y*-value changes before the *x*-value.

## Custom curves

Curves are typically not used directly, instead being passed to *line*.curve and *area*.curve. However, you can define your own curve implementation should none of the built-in curves satisfy your needs using the following interface; see the curveLinear source for an example implementation. You can also use this low-level interface with a built-in curve type as an alternative to the line and area generators.

*curve*.areaStart()

Indicates the start of a new area segment. Each area segment consists of exactly two line segments: the topline, followed by the baseline, with the baseline points in reverse order.

*curve*.areaEnd()

Indicates the end of the current area segment.

*curve*.lineStart()

Indicates the start of a new line segment. Zero or more points will follow.

*curve*.lineEnd()

Indicates the end of the current line segment.

*curve*.point(*x*, *y*)

Indicates a new point in the current line segment with the given *x*- and *y*-values.