Skip to content

Instantly share code, notes, and snippets.

@eclecticlogic
Last active May 11, 2020 00:19
Show Gist options
  • Save eclecticlogic/e46120cb719d38f5360e to your computer and use it in GitHub Desktop.
Save eclecticlogic/e46120cb719d38f5360e to your computer and use it in GitHub Desktop.
Fits a Cubic Bezier curve and allows you to treat it as y = f(x)
import java.util.HashMap;
import java.util.Map;
/**
* @author kabram.
*
*/
public class CubicBezierCurve {
private Point p0, p1, p2, p3;
private final Map<Double, Double> precomputed = new HashMap<>();
public void setEndPoints(Point start, Point end) {
p0 = start;
p3 = end;
}
public void setControlPoints(Point c1, Point c2) {
p1 = c1;
p2 = c2;
}
public double get(double x, double precision) {
if (precomputed.containsKey(x)) {
return precomputed.get(x);
} else {
double t = (x - p0.x) / (p3.x - p0.x);
double x1 = getX(t);
double left = 0.0;
double right = 1.0;
while (Math.abs(x1 - x) > precision) {
if (x1 < x) {
left = t;
} else {
right = t;
}
t = (left + right) / 2.0;
x1 = getX(t);
}
return getY(t);
}
}
private double getY(double t) {
double t2 = Math.pow(t, 2);
double t3 = Math.pow(t, 3);
double a = Math.pow(1 - t, 3);
double b = 3.0 * (t - 2.0 * t2 + t3);
double c = 3.0 * (t2 - t3);
double d = t3;
return a * p0.y + b * p1.y + c * p2.y + d * p3.y;
}
private double getX(double t) {
double t2 = Math.pow(t, 2);
double t3 = Math.pow(t, 3);
double a = Math.pow(1 - t, 3);
double b = 3.0 * (t - 2.0 * t2 + t3);
double c = 3.0 * (t2 - t3);
double d = t3;
return a * p0.x + b * p1.x + c * p2.x + d * p3.x;
}
/**
* @param step Pre-compute values base on step value of x from start.x to end.x.
*/
public void precompute(double step, double precision) {
double x = p0.x;
while (x <= p3.x * Math.signum(step)) {
precomputed.put(x, get(x, precision));
x += step;
}
}
public static void main(String[] args) {
CubicBezierCurve curve = new CubicBezierCurve();
curve.setEndPoints(new Point(0, 10), new Point(20, 0));
curve.setControlPoints(new Point(0, 6), new Point(12, 0));
System.out.println(curve.get(0.18, 0.001));
}
public static class Point {
double x;
double y;
public Point() {
super();
}
public Point(double x, double y) {
super();
this.x = x;
this.y = y;
}
public static Point xy(double x, double y) {
return new Point(x, y);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment