## bezier 1.1.0

bezier.dart is a simple open-source Dart library for handling 2D Bézier curve math.

The library was developed, documented, and published by Aaron Barrett and Isaac Barrett. It is based heavily on the work of Pomax, including his excellent Primer on Bézier Curves and his original JavaScript library, Bezier.js.

We're trying to design bezier.dart to be both platform independent and context independent. You can run the library anywhere you can run Dart: in a web browser, in a Flutter application, server side, and beyond.

For live examples of the library's API, see the project page at dartographer.com/bezier.

## Features #

• Supports both quadratic and cubic two dimensional Bézier curves
• Calculate the coordinates of a point at any parameter value `t` along a curve
• Derivative and normal values at any `t` parameter value
• Accurate length approximations (using the Legendre-Gauss quadrature algorithm)
• Split a curve into equivalent subcurves between any `t` parameter values
• Find the extrema of a curve on both the x and y axes
• Calculate the bounding box for a curve
• Given any curve, derive a new curve, offset from the original curve along the normals at a given distance
• Calculate the positions of a curve's intersections with itself, with another curve, or with a line segment
• Find points evenly spaced along the arc length of a curve
• Heavily documented and tested

## Getting Started #

1. Add the following to your project's pubspec.yaml and run pub get.
``````dependencies:
bezier: any
``````
1. Import bezier.dart from a file in your project. In most cases you will also want to import the vector_math library.
``````import "package:vector_math/vector_math.dart";
import "package:bezier/bezier.dart";
``````

## Examples #

• Instantiate a Bézier curve.
``````import "package:vector_math/vector_math.dart";
import "package:bezier/bezier.dart";

void main() {
// bezier.dart supports both quadratic curves...
new Vector2(-40.0, -40.0),
new Vector2(30.0, 10.0),
new Vector2(55.0, 25.0)
]);

// ...and cubic curves!
final cubicCurve = new CubicBezier([
new Vector2(10.0, 10.0),
new Vector2(70.0, 95.0),
new Vector2(25.0, 20.0),
new Vector2(15.0, 80.0)
]);
}
``````
• Compute a point along a curve at `t` of `0.75`.
``````import "package:vector_math/vector_math.dart";
import "package:bezier/bezier.dart";

void main() {
new Vector2(10.0, 10.0),
new Vector2(70.0, 95.0),
new Vector2(15.0, 80.0)
]);

final computedPoint = curve.pointAt(0.75);
}
``````
• Split a curve between the `t` parameter values of `0.2` and `0.6`.
``````import "package:vector_math/vector_math.dart";
import "package:bezier/bezier.dart";

void main() {
final curve = new CubicBezier([
new Vector2(10.0, 10.0),
new Vector2(70.0, 95.0),
new Vector2(25.0, 20.0),
new Vector2(15.0, 80.0)
]);

final subcurve = curve.subcurveBetween(0.2, 0.6);
}
``````
• Find the intersection `t` values between a curve and a line segment.
``````import "package:vector_math/vector_math.dart";
import "package:bezier/bezier.dart";

void main() {
new Vector2(10.0, 500.0),
new Vector2(50.0, 0.0),
new Vector2(90.0, 500.0)
]);

final lineStart = new Vector2(0.0, 400.0);
final lineEnd = new Vector2(100.0, 410.0);

final intersections = curve.intersectionsWithLineSegment(lineStart, lineEnd);
}
``````
• Derive an offset curve (composed of a series of subcurves) at distance `12.0`.
``````import "package:vector_math/vector_math.dart";
import "package:bezier/bezier.dart";

void main() {
final curve = new CubicBezier([
new Vector2(10.0, 10.0),
new Vector2(15.0, 95.0),
new Vector2(20.0, 95.0),
new Vector2(25.0, 10.0)
]);

final subcurves = curve.offsetCurve(12.0);
}
``````

## Style, Formatting, Philosophy #

We've made our best effort to conform to the recommendations outlined in the Effective Dart guide. Accordingly, this library is formatted using dartfmt.

As fervent believers in the value of clean code, we are constantly seeking to improve the library and make it easier to work with. Please alert us to any issues you notice, no matter how trivial. We wholeheartedly welcome criticism and friendly debate! 🤓

## Running Automated Tests #

To run the test cases from the terminal, run the following command from the bezier.dart root directory.

``````pub run test
``````

Most IDEs now provide interfaces for running tests, which are generally easier to work with. In most cases you can simply right click on a test file or directory in the project tree view and select the menu option to run the selected tests.

## Submitting bugs, requesting features #

Please file feature requests and bugs using the GitHub issues tab.

# Changelog - bezier #

## v 1.1.0 - January 30 2019 #

• Added `nearestTValue` method to `Bezier` class, based on work by @luigi-rosso -- Thanks!
• Added `indexOfNearestPoint` method (to support `nearestTValue`) in `bezier_tools`
• Added unit tests for both new methods in `bezier_nearest_methods_test`

## v 1.0.3 - December 20 2018 #

• Corrected the version number in the pubspec, since I forgot to commit it in 1.0.2

## v 1.0.2 - December 20 2018 #

• Added example directory with a simple HTML demo app
• Adjusted the description in pubspec again to meet character count limits

## v 1.0.1 - December 12 2018 #

• Adjusted minor details in pubspec
• Listed GitHub page as package homepage

## v 1.0.0 - December 12 2018 #

• First public release
• Published to Pub at [https://pub.dartlang.org/packages/bezier]

## v 0.0.0 - September 26 2018 #

• Initial release

example/main.dart

``````import "dart:html";
import "dart:math";
import "package:vector_math/vector_math.dart";
import "package:bezier/bezier.dart";

const oscillationRateX = 0.63;
const oscillationRateY = 0.79;

const slitherRate = 0.0025;

const timeOffsets = [0.0, 9511.14, 2922.25, 363.31];

const normalLinesCount = 125;
const normalLineLength = 70.0;

const outlineDistance = 50.0;

final canvas = querySelector("#canvas") as CanvasElement;
final context = canvas.context2D;

void main() {
animate();
}

void animate() {
window.animationFrame.then(drawFrame);
}

void drawFrame(num time) {
clearCanvas();

final points = pointsAtTime(time);
final curve = new CubicBezier(points);

drawMainCurve(curve);

//////////////////////////////////////////////////////////////////
// Try uncommenting the following lines to see different examples:
//////////////////////////////////////////////////////////////////

drawNormalLines(curve);
//  drawBoundingBox(curve);
//  drawOutlines(curve);
//  drawLineSegmentIntersections(curve, time);
//  drawExtrema(curve);

//////////////////////////////////////////////////////////////////

animate();
}

List<Vector2> pointsAtTime(double time) => timeOffsets.map((offset) {
final adjustedTime = slitherRate * time + offset;
return new Vector2(
canvas.width *
canvas.height *
}).toList();

void clearCanvas() {
context.clearRect(0.0, 0.0, canvas.width, canvas.height);
}

void drawCircle(Vector2 center, {double radius = 3.0}) {
context
..beginPath()
..arc(center.x, center.y, radius, 0.0, 2.0 * pi)
..stroke()
..closePath();
}

void drawCurve(CubicBezier curve) {
final points = curve.points;

context.moveTo(points[0].x, points[0].y);
context.bezierCurveTo(curve.points[1].x, curve.points[1].y, curve.points[2].x,
curve.points[2].y, curve.points[3].x, curve.points[3].y);
}

void drawMainCurve(CubicBezier curve) {
context.setStrokeColorRgb(0, 0, 0);

context.beginPath();
drawCurve(curve);
context.stroke();
}

void drawNormalLines(CubicBezier curve) {
final derivativePoints = curve.firstOrderDerivativePoints;

context.setStrokeColorRgb(0, 0, 255);

context.beginPath();
for (var lineIndex = 0; lineIndex < normalLinesCount; lineIndex++) {
final t = (lineIndex + 1) / (normalLinesCount + 1);

final pointOnCurve = curve.pointAt(t);
final normal =
curve.normalAt(t, cachedFirstOrderDerivativePoints: derivativePoints);
final offset = normal * normalLineLength;

final positiveOffsetPoint = pointOnCurve + offset;
final negativeOffsetPoint = pointOnCurve - offset;

context.moveTo(negativeOffsetPoint.x, negativeOffsetPoint.y);
context.lineTo(positiveOffsetPoint.x, positiveOffsetPoint.y);
}
context.stroke();
}

void drawBoundingBox(CubicBezier curve) {
final boundingBox = curve.boundingBox;

final min = boundingBox.min;
final max = boundingBox.max;
final width = max.x - min.x;
final height = max.y - min.y;

context.setStrokeColorRgb(0, 255, 0);
context.strokeRect(min.x, min.y, width, height);
}

void drawOutlines(CubicBezier curve) {
final outlineCurves = []

context.setStrokeColorRgb(255, 0, 255);

context.beginPath();
outlineCurves.forEach((outlineCurve) => drawCurve(outlineCurve));
context.stroke();
}

Vector2 lineSegmentPointAtTime(double radius, double time) => new Vector2(
canvas.width * (0.5 + radius * cos(time * 0.00042)),
canvas.height * (0.5 + radius * sin(time * 0.00042)),
);

void drawLineSegmentIntersections(CubicBezier curve, double time) {
final startPoint = lineSegmentPointAtTime(-0.25, time);
final endPoint = lineSegmentPointAtTime(0.35, time);

context
..setStrokeColorRgb(255, 127, 0)
..beginPath()
..moveTo(startPoint.x, startPoint.y)
..lineTo(endPoint.x, endPoint.y)
..stroke();

final intersectionTValues =
curve.intersectionsWithLineSegment(startPoint, endPoint);

context.setStrokeColorRgb(255, 0, 0);
intersectionTValues.forEach((t) {
final intersectionPoint = curve.pointAt(t);
drawCircle(intersectionPoint);
});
}

void drawExtrema(CubicBezier curve) {
final xExtremaTValues = curve.extremaOnX;
final yExtremaTValues = curve.extremaOnY;

context.setStrokeColorRgb(255, 0, 0);
xExtremaTValues.forEach((t) => drawCircle(curve.pointAt(t)));

context.setStrokeColorRgb(0, 191, 0);
yExtremaTValues.forEach((t) => drawCircle(curve.pointAt(t)));
}
``````

## Use this package as a library

### 1. Depend on it

``````
dependencies:
bezier: ^1.1.0

``````

### 2. Install it

You can install packages from the command line:

with pub:

``````
\$ pub get

``````

with Flutter:

``````
\$ flutter pub get

``````

Alternatively, your editor might support `pub get` or `flutter pub get`. Check the docs for your editor to learn more.

### 3. Import it

Now in your Dart code, you can use:

``````
import 'package:bezier/bezier.dart';
``````
 Popularity: Describes how popular the package is relative to other packages. [more] 89 Health: Code health derived from static analysis. [more] 75 Maintenance: Reflects how tidy and up-to-date the package is. [more] 100 Overall: Weighted score of the above. [more] 87

We analyzed this package on Jan 29, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

• Dart: 2.7.1
• pana: 0.13.4

#### Health suggestions

Fix `lib/src/bezier.dart`. (-17.76 points)

Analysis of `lib/src/bezier.dart` reported 39 hints, including:

line 29 col 14: Unnecessary new keyword.

line 31 col 14: Unnecessary new keyword.

line 33 col 14: Unnecessary new keyword.

line 66 col 14: Unnecessary new keyword.

line 128 col 21: Unnecessary new keyword.

Fix `lib/src/bezier_tools.dart`. (-7.71 points)

Analysis of `lib/src/bezier_tools.dart` reported 16 hints, including:

line 97 col 28: Unnecessary new keyword.

line 101 col 19: Unnecessary new keyword.

line 114 col 24: Unnecessary new keyword.

line 117 col 24: Unnecessary new keyword.

line 128 col 27: Unnecessary new keyword.

Fix `lib/src/quadratic_bezier.dart`. (-2.96 points)

Analysis of `lib/src/quadratic_bezier.dart` reported 6 hints, including:

line 12 col 14: Unnecessary new keyword.

line 30 col 19: Unnecessary new keyword.

line 43 col 20: Unnecessary new keyword.

line 52 col 30: Unnecessary new keyword.

line 60 col 27: Unnecessary new keyword.

Fix `lib/src/cubic_bezier.dart`. (-1.49 points)

Analysis of `lib/src/cubic_bezier.dart` reported 3 hints:

line 12 col 14: Unnecessary new keyword.

line 31 col 19: Unnecessary new keyword.

line 50 col 29: Unnecessary new keyword.

Fix `lib/src/even_spacer.dart`. (-1 points)

Analysis of `lib/src/even_spacer.dart` reported 2 hints:

line 21 col 14: Unnecessary new keyword.

line 38 col 12: Unnecessary new keyword.

#### Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0 <3.0.0
vector_math ^2.0.0 2.0.8
Dev dependencies
test ^1.0.0