Skip to content

Instantly share code, notes, and snippets.

@rutvik110
Last active December 23, 2022 17:47
Show Gist options
  • Save rutvik110/215e6447c45abd06ad63b2613a31ecf5 to your computer and use it in GitHub Desktop.
Save rutvik110/215e6447c45abd06ad63b2613a31ecf5 to your computer and use it in GitHub Desktop.
//get the position of the latest coordinate on the curve at any point in animation based on animation position(t)
class BezierTween extends Tween<Offset> {
BezierTween({required this.begin, required this.end, required this.control})
: super(begin: begin, end: end);
@override
final Offset begin;
@override
final Offset end;
final Offset control;
@override
Offset lerp(double t) {
final double t1 = 1 - t;
return begin * t1 * t1 + control * 2 * t1 * t + end * t * t;
}
}
// Implementation of De Casteljau's algorithm in dart
// ref - https://pomax.github.io/bezierinfo/#splitting, https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm,
List<List<math.Point<num>>> drawCurvePoint(List<math.Point> points, double t) {
final List<math.Point<num>> left = <math.Point>[];
final List<math.Point<num>> right = <math.Point>[];
if (points.length == 1) {
left.add(points[0]);
right.add(points[0]);
return [left, right];
} else {
final List<math.Point<num>> newpoints =
List<math.Point>.filled(points.length - 1, const math.Point(0, 0));
for (int i = 0; i < newpoints.length; i++) {
if (i == 0) {
left.add(points[i]);
}
if (i == newpoints.length - 1) {
right.add(points[i + 1]);
}
newpoints[i] = math.Point(points[i].x, points[i].y) * (1 - t) +
math.Point(points[i + 1].x, points[i + 1].y) * t;
}
final List<List<math.Point<num>>> newPoints = drawCurvePoint(newpoints, t);
left.addAll(newPoints[0]);
right.addAll(newPoints[1]);
return [left, right];
}
}
// example usage
// get the current coordinate on the curve
final Offset currentPosition = BezierTween(
begin: startingPoint,
end: destination,
control: controlPoint,
).evaluate(animationController);
endingPoint = currentPosition;
// get the first half and second half of the arcs based on animation position(t)
final List<List<math.Point<num>>> segments = drawCurvePoint(
[
math.Point(startingPoint.dx, startingPoint.dy),
math.Point(controlPoint.dx, controlPoint.dy),
math.Point(destination.dx, destination.dy),
],
animationController.value,
);
// segment[0] is list points forming the first half of the curve, read more abt how splitting is done here->https://pomax.github.io/bezierinfo/#splitting
startingPoint = Offset(
segments[0][0].x.toDouble(),
segments[0][0].y.toDouble(),
);
controlPoint = Offset(
segments[0][1].x.toDouble(),
segments[0][1].y.toDouble(),
);
endingPoint = Offset(
segments[0][2].x.toDouble(),
segments[0][2].y.toDouble(),
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment