# Curve

## constructor

`g.Curve(p1 [, p2, p3, p4])`

Return a new curve object with start at point `p1`

, control points at `p2`

and `p3`

, and end at `p4`

. All points are passed through the `Point`

constructor so they can also be passed in string form. Examples:

`var c = new g.Curve(new g.Point(10, 10), new g.Point(10, 40), new g.Point(50, 40), new g.Point(50, 10));`

var c = new g.Curve('10 10', '10 40', '50 40', '50 10');

var c = new g.Curve('10@10', '10@40', '50@40', '50@10');

The constructor also accepts a single Curve object as an argument; it creates a new curve with points cloned from the provided curve.

## Methods

### bbox()

`curve.bbox()`

Return a rectangle that is the tight bounding box of the curve (i.e. not including the curve control points).

### clone()

`curve.clone()`

Return another curve which is a clone of the curve.

### closestPoint()

`curve.closestPoint(point [, opt])`

Return the point on the curve that lies closest to `point`

.

The function uses the same algorithm as the `curve.closestPointT()`

function. The point at `t`

closest to `point`

is returned.

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1%.

The `opt.subdivisions`

property may be specified, directly providing an array of pre-computed curve subdivisions with which to begin the algorithm. Use the `curve.getSubdivisions()`

function to obtain an array of curve subdivisions. The `opt.precision`

property is still necessary, however; it determines the precision of the point search algorithm.

### closestPointLength()

`curve.closestPointLength(point [, opt])`

Return the length of the curve up to the point that lies closest to `point`

.

The function uses the same algorithm as the `curve.closestPointT()`

function. The length of the curve at `t`

closest to `point`

is returned.

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1%.

The `opt.subdivisions`

property may be specified, directly providing an array of pre-computed curve subdivisions with which to begin the algorithm. Use the `curve.getSubdivisions()`

function to obtain an array of curve subdivisions. The `opt.precision`

property is still necessary, however; it determines the precision of the point search algorithm.

### closestPointNormalizedLength()

`curve.closestPointNormalizedLength(point [, opt])`

Return the normalized length (distance from the start of the curve / total curve length) of the curve up to the point that lies closest to `point`

.

The function uses the same algorithm as the `curve.closestPointT()`

function. The normalized length of the curve at `t`

closest to `point`

is returned.

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1%.

The `opt.subdivisions`

property may be specified, directly providing an array of pre-computed curve subdivisions with which to begin the algorithm. Use the `curve.getSubdivisions()`

function to obtain an array of curve subdivisions. The `opt.precision`

property is still necessary, however; it determines the precision of the point search algorithm.

### closestPointT()

`curve.closestPointT(point [, opt])`

Return the `t`

value of the point on the curve that lies closest to `point`

.

The curve is first subdivided, according to `opt.precision`

(refer to `curve.length()`

documentation for more information about precision and curve flattening). Then, one subdivision is identified whose endpoints are the closest to `point`

. A binary search is then performed on that subdivision, until a curve is found whose diffrence between endpoints' distance to `point`

lies within `opt.precision`

. The `t`

value of the closest endpoint is returned by the function.

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1%.

`opt.subdivisions`

property may be specified, directly providing an array of pre-computed curve subdivisions with which to begin the algorithm. Use the `curve.getSubdivisions()`

function to obtain an array of curve subdivisions. The `opt.precision`

property is still necessary, however; it determines the precision of the point search algorithm.

### closestPointTangent()

`curve.closestPointTangent(point [, opt])`

Return a line that is tangent to the curve at the point that lies closest to `point`

.

The tangent line starts at the identified closest point. The direction from `start`

to `end`

is the same as the direction of the curve at the closest point.

If the control points of the curve all lie at the same coordinates, `null`

is returned (it is impossible to determine the slope of a point). The `curve.isDifferentiable()`

function may be used in advance to determine whether tangents can exist for a given curve.

The function uses the same algorithm as the `curve.closestPointT()`

function. The tangent at `t`

closest to `point`

is returned.

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1%.

`opt.subdivisions`

property may be specified, directly providing an array of pre-computed curve subdivisions with which to begin the algorithm. Use the `curve.getSubdivisions()`

function to obtain an array of curve subdivisions. The `opt.precision`

property is still necessary, however; it determines the precision of the point search algorithm.

### containsPoint()

`curve.containsPoint(p [, opt])`

Return `true`

if the point `p`

is inside the area surrounded by the curve (inclusive). Return `false`

otherwise. Uses the even-odd algorithm to resolve self-intersections.

Uses the `curve.toPolyline()`

function in the background. The precision of the calculation may be adjusted by passing the `opt.precision`

and `opt.subdivisions`

properties.

### divideAt()

`curve.divideAt(ratio [, opt])`

Divide the curve into two curves at the point that lies `ratio`

(normalized length) away from the beginning of the curve.

Returns an array with two new curves without modifying the original curve. The function expects `ratio`

to lie between 0 and 1; values outside the range are constrained to 0 and 1, respectively.

This function mirrors the functionality of the `line.divideAt()`

function. If it is necessary to divide the curve at a certain `t`

value instead, use the `curve.divideAtT()`

function.

The function uses the same algorithm as the `curve.divideAtLength()`

function.

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1%.

The `opt.subdivisions`

property may be specified, directly providing an array of pre-computed curve subdivisions from which to calculate curve length. Use the `curve.getSubdivisions()`

function to obtain an array of curve subdivisions. The `opt.precision`

property is still necessary, however; it determines the precision of the point search algorithm.

### divideAtLength()

`curve.divideAtLength(length [, opt])`

Divide the curve into two curves at the point that lies `length`

away from the beginning of the curve.

Returns an array with two new curves without modifying the original curve. If negative `length`

is provided, the algorithm starts looking from the end of the curve. If `length`

is higher than curve length, the curve is divided at the closest endpoint instead.

The curve is first subdivided, according to `opt.precision`

(refer to `curve.length()`

documentation for more information about precision and curve flattening). Then, one subdivision is identified which contains the point at `length`

. A binary search is then performed on that subdivision, until a curve is found whose endpoint lies within `opt.precision`

away from `length`

. That endpoint is used by the function to divide the curve.

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1%.

As a rule of thumb, increasing precision by 1 doubles the number of operations needed to find the point to be returned (this is on top of the cost of curve subdivision); exact numbers vary for every individual curve, however.

The `opt.subdivisions`

property may be specified, directly providing an array of pre-computed curve subdivisions from which to calculate curve length. Use the `curve.getSubdivisions()`

function to obtain an array of curve subdivisions. The `opt.precision`

property is still necessary, however; it determines the precision of the point search algorithm.

### divideAtT()

`curve.divideAtT(t)`

Divide the curve into two curves at the point specified by `t`

.

Returns an array with two new curves without modifying the original curve. The function expects `t`

to lie between 0 and 1; values outside the range are constrained to 0 and 1, respectively.

This function is not a counterpart to the `line.divideAt()`

function. The relationship between `t`

and distance along a curve is complex and non-linear. If it is necessary to divide the curve at a certain `ratio`

(normalized length) away from beginning of the curve, use the `curve.divideAt()`

function.

### endpointDistance()

`curve.endpointDistance()`

Return the distance between curve `start`

and `end`

points.

### equals()

`curve.equals(otherCurve)`

Return `true`

if the curve exactly equals the other curve.

### getSkeletonPoints()

`curve.getSkeletonPoints(t)`

Return an object that contains five points necessary for dividing curves.

The function expects `t`

to lie between 0 and 1; values outside the range are constrained to 0 and 1, respectively.

The returned object has the following properties:

`startControlPoint1` | First curve's `controlPoint1` . |
---|---|

`startControlPoint2` | First curve's `controlPoint2` . |

`divider` | The point at `t` ; `end` point of the first curve and `start` point of the second curve. |

`dividerControlPoint1` | Second curve's `controlPoint1` . |

`dividerControlPoint2` | Second curve's `controlPoint2` |

If only the point at `t`

is needed, use the `curve.pointAtT()`

function.

If the two divided curves are needed, rather than their control points, use the `curve.divideAtT()`

function.

### getSubdivisions()

`curve.getSubdivisions([opt])`

Return an array of curves obtained by recursive halving of the curve up to a given precision.

Halving is not defined in terms of length, but in terms of the `t`

parameter. The curves are subdivided at `t = 0.5`

.

This is an intermediary function. Curve functions that rely on length calculations must work with flattened curves, with points obtained by curve subdivision at an arbitrary precision level. Refer to `curve.length()`

documentation for more information about precision and curve flattening.

This function makes it possible to avoid expensive re-subdivisions of the curve when several operations need to be performed at the same level of precision (for example, obtaining the length of the curve and then finding the point at 10% length). The returned array may be passed to all such functions as the `opt.subdivisions`

property.

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1%.

### isDifferentiable()

`curve.isDifferentiable()`

Return `true`

if a tangent line can be found for the curve.

Tangents cannot be found if all of the curve control points are coincident (the curve appears to be a point).

### length()

`curve.length([opt])`

Return the length of the curve.

The curve length is a flattened length. This means that there will always be a difference between the reported length and the real length of the curve. (The returned curve length is always lower than the actual curve length.) That being said, the observed error can be constrained to an arbitrary threshold - here determined by `opt.precision`

.

The `opt.precision`

property is logarithmic, which means that increasing precision by 1 decreases observed error in length by a factor of 10. (For example, precision 3 leads to an observed error of less than 0.1%, precision 4 guarantees an observed error of less than 0.01%, etc.)

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1%.

As a rule of thumb, increasing precision by 1 quadruples the number of operations needed to determine the length; exact numbers vary for every individual curve, however. Precision 3 is considered good enough when drawing curve approximations, and precision 4 is considered good enough for mapping curve `t`

values to curve length. (Precision 4 should be the highest necessary for any practical use.)

The measure used, observed error (difference between subsequent observed lengths), is not a measure of actual error (difference between observed length and the actual length); it is a necessary substitution, however. The actual curve length cannot be precisely determined in the general case, and obtaining flattened length at maximum precision is not feasible for every single length calculation. Still, actual error is generally 2-3 times lower than observed error, so `opt.precision`

can be seen as an upper bound on the length error with a high degree of confidence.

Instead of `opt.precision`

, the `opt.subdivisions`

property may be specified, directly providing an array of pre-computed curve subdivisions from which to calculate curve length. This is useful when several operations need to be performed with the same curve at the same level of precision (for example, obtaining the length of the curve and then finding the point at 10% length). Use the `curve.getSubdivisions()`

function to obtain an array of curve subdivisions.

### lengthAtT()

`curve.lengthAtT(t [, opt])`

Return the length of the curve up to the point specified by `t`

.

The curve is divided at `t`

and the length of the first subcurve is returned. For more information about curve length calculation refer to `curve.length()`

documentation.

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1%.

This method does make use of the `opt.subdivisions`

property.

### pointAt()

`curve.pointAt(ratio [, opt])`

Return a point on the curve that lies `ratio`

(normalized length) away from the beginning of the curve.

The function expects `ratio`

to lie between 0 and 1; values outside the range are constrained to 0 and 1, respectively.

This function mirrors the functionality of the `line.pointAt()`

function. If the point at a given `t`

value is needed instead, use the `curve.pointAtT()`

function.

The function uses the same algorithm as the `curve.pointAtLength()`

function.

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1%.

The `opt.subdivisions`

property may be specified, directly providing an array of pre-computed curve subdivisions from which to calculate curve length. Use the `curve.getSubdivisions()`

function to obtain an array of curve subdivisions. The `opt.precision`

property is still necessary, however; it determines the precision of the point search algorithm.

### pointAtLength()

`curve.pointAtLength(length [, opt])`

Return a point on the curve that lies `length`

away from the beginning of the curve.

If negative `length`

is provided, the algorithm starts looking from the end of the curve. If `length`

is higher than curve length, the closest curve endpoint is returned instead.

The curve is first subdivided, according to `opt.precision`

(refer to `curve.length()`

documentation for more information about precision and curve flattening). Then, one subdivision is identified which contains the point at `length`

. A binary search is then performed on that subdivision, until a curve is found whose endpoint lies within `opt.precision`

away from `length`

. That endpoint is returned by the function.

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1%.

As a rule of thumb, increasing precision by 1 doubles the number of operations needed to find the point to be returned (this is on top of the cost of curve subdivision); exact numbers vary for every individual curve, however.

`opt.subdivisions`

property may be specified, directly providing an array of pre-computed curve subdivisions from which to calculate curve length. Use the `curve.getSubdivisions()`

function to obtain an array of curve subdivisions. The `opt.precision`

property is still necessary, however; it determines the precision of the point search algorithm.

### pointAtT()

`curve.pointAtT(t)`

Return a point on the curve at a point specified by `t`

.

The function expects `t`

to lie between 0 and 1; values outside the range are constrained to 0 and 1, respectively.

This function is not a counterpart to the `line.pointAt()`

function. The relationship between `t`

and distance along a curve is complex and non-linear. If a point at a certain `ratio`

(normalized length) away from beginning of the curve is needed, use the `curve.pointAt()`

function.

### round()

`curve.round([precision])`

Round all coordinates of the curve to the given precision.

Default precision is `0`

.

Modifies this curve in-place, and returns it.

### scale()

`curve.scale(sx, sy [, origin])`

Scale the curve by `sx`

and `sy`

about the given origin.

If origin is not specified, the curve is scaled around 0,0.

### tAt()

`curve.tAt(ratio [, opt])`

Return the `t`

value of the point that lies `ratio`

(normalized length) away from the beginning of the curve.

The function expects `ratio`

to lie between 0 and 1; values outside the range are constrained to 0 and 1, respectively.

The function uses the same algorithm as the `curve.tAtLength()`

function.

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1%.

`opt.subdivisions`

property may be specified, directly providing an array of pre-computed curve subdivisions from which to calculate curve length. Use the `curve.getSubdivisions()`

function to obtain an array of curve subdivisions. The `opt.precision`

property is still necessary, however; it determines the precision of the point search algorithm.

### tAtLength()

`curve.tAtLength(length [, opt])`

Return the `t`

value of the point that lies `length`

away from the beginning of the curve.

If negative `length`

is provided, the algorithm starts looking from the end of the curve. If `length`

requested is higher than curve length, the `t`

of the closest curve endpoint (0 or 1) is returned instead.

The curve is first subdivided, according to `opt.precision`

(refer to `curve.length()`

documentation for more information about precision and curve flattening). Then, one subdivision is identified which contains the point at `length`

. A binary search is then performed on that subdivision, until a curve is found whose endpoint lies within `opt.precision`

away from `length`

. The `t`

value of that endpoint is returned by the function.

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1%.

`opt.subdivisions`

property may be specified, directly providing an array of pre-computed curve subdivisions from which to calculate curve length. Use the `curve.getSubdivisions()`

function to obtain an array of curve subdivisions. The `opt.precision`

property is still necessary, however; it determines the precision of the point search algorithm.

### tangentAt()

`curve.tangentAt(ratio [, opt])`

Return a line that is tangent to the curve at a point that lies `ratio`

(normalized length) away from the beginning of the curve.

The function expects `ratio`

to lie between 0 and 1; values outside the range are constrained to 0 and 1, respectively.

The tangent line starts at the specified point. The direction from `start`

to `end`

is the same as the direction of the curve at the specified point.

If the control points of the curve all lie at the same coordinates, `null`

is returned (it is impossible to determine the slope of a point). The `curve.isDifferentiable()`

function may be used in advance to determine whether tangents can exist for a given curve.

The function uses the same algorithm as the `curve.tangentAtLength()`

function.

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1%.

`opt.subdivisions`

property may be specified, directly providing an array of pre-computed curve subdivisions from which to calculate curve length. Use the `curve.getSubdivisions()`

function to obtain an array of curve subdivisions. The `opt.precision`

property is still necessary, however; it determines the precision of the point search algorithm.

### tangentAtLength()

`curve.tangentAtLength(length [, opt])`

Return a line that is tangent to the curve at a point that lies `length`

away from the beginning of the curve.

If negative `length`

is provided, the algorithm starts looking from the end of the curve. If `length`

is higher than curve length, a line tangent to the closest curve endpoint is returned instead.

The tangent line starts at the specified point. The direction from `start`

to `end`

is the same as the direction of the curve at the specified point.

If the control points of the curve all lie at the same coordinates, `null`

is returned (it is impossible to determine the slope of a point). The `curve.isDifferentiable()`

function may be used in advance to determine whether tangents can exist for a given curve.

The curve is first subdivided, according to `opt.precision`

(refer to `curve.length()`

documentation for more information about precision and curve flattening). Then, one subdivision is identified which contains the point at `length`

. A binary search is then performed on that subdivision, until a curve is found whose endpoint lies within `opt.precision`

away from `length`

. That endpoint is used as the start of the tangent line.

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1%.

`opt.subdivisions`

property may be specified, directly providing an array of pre-computed curve subdivisions from which to calculate curve length. Use the `curve.getSubdivisions()`

function to obtain an array of curve subdivisions. The `opt.precision`

property is still necessary, however; it determines the precision of the point search algorithm.

### tangentAtT()

`curve.tangentAtT(t)`

Return a line that is tangent to the curve at point specified by `t`

.

The function expects `t`

to lie between 0 and 1; values outside the range are constrained to 0 and 1, respectively.

The tangent line starts at the specified point. The direction from `start`

to `end`

is the same as the direction of the curve at the specified point.

`null`

is returned (it is impossible to determine the slope of a point). The `curve.isDifferentiable()`

function may be used in advance to determine whether tangents can exist for a given curve.

### toPoints()

`curve.toPoints([opt])`

Return an array of points that approximate the curve at given precision.

The points obtained are endpoints of curve subdivisions whose flattened length is up to the specified precision level away from actual curve length. Refer to `curve.length()`

documentation for more information about precision and curve flattening.

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1% in flattened curve length.

Instead of `opt.precision`

, the `opt.subdivisions`

property may be specified, directly providing an array of pre-computed curve subdivisions from which to obtain the array of points. Use the `curve.getSubdivisions()`

function to obtain an array of curve subdivisions.

### toPolyline()

`curve.toPolyline([opt])`

Return a polyline that approximates the curve at given precision.

The polyline points are found as endpoints of curve subdivisions whose flattened length is up to the specified precision level away from actual curve length. Refer to `curve.length()`

documentation for more information about precision and curve flattening.

The default value for `opt.precision`

is 3; this corresponds to maximum observed error of 0.1% in flattened curve length.

Instead of `opt.precision`

, the `opt.subdivisions`

property may be specified, directly providing an array of pre-computed curve subdivisions from which to obtain the polyline. Use the `curve.getSubdivisions()`

function to obtain an array of curve subdivisions.

### toString()

`curve.toString()`

Return the curve represented as a string.

`new g.Curve('10 10', '10 20', '20 20', '20 10').toString() = "10@10 10@20 20@20 20@10"`

### translate()

`curve.translate(tx [, ty])`

Translate the curve by `tx`

on the x-axis and by `ty`

on the y-axis.

If only `tx`

is specified and is a number, `ty`

is considered to be zero. If only `tx`

is specified and is an object, it is considered to be a point or an object in the form `{ x: [number], y: [number] }`

## Static methods

### throughPoints()

`g.Curve.throughPoints(points)`

Return an array of cuic bezier curves that defines a curve passing through provided `points`

.

This method automatically computes the cubic bezier control points necessary to create a smooth curve with `points`

as intermediary endpoints. An error is thrown if an array with fewer than two points is provided.

The result of this function may be provided directly to the `g.Path()`

constructor in order to create a Path object from these curves.