package org.oscim.utils.geom;
import java.util.ArrayList;
import java.util.List;
import org.oscim.core.Point;
public class BezierPath {
/**
* from http://paulbourke.net/geometry/bezier/index.html
* Three control point Bezier interpolation
* mu ranges from 0 to 1, start to end of the curve
*/
public static Point bezier3(Point p1, Point p2, Point p3, double mu) {
double mum1, mum12, mu2;
Point p = new Point();
mu2 = mu * mu;
mum1 = 1 - mu;
mum12 = mum1 * mum1;
p.x = p1.x * mum12 + 2 * p2.x * mum1 * mu + p3.x * mu2;
p.y = p1.y * mum12 + 2 * p2.y * mum1 * mu + p3.y * mu2;
//p.z = p1.z * mum12 + 2 * p2.z * mum1 * mu + p3.z * mu2;
return (p);
}
/**
* from http://paulbourke.net/geometry/bezier/index.html
* Four control point Bezier interpolation
* mu ranges from 0 to 1, start to end of curve
*/
public static Point cubicBezier(Point p1, Point p2, Point p3, Point p4, double mu) {
double mum1, mum13, mu3;
Point p = new Point();
mum1 = 1 - mu;
mum13 = mum1 * mum1 * mum1;
mu3 = mu * mu * mu;
p.x = mum13 * p1.x + 3 * mu * mum1 * mum1 * p2.x + 3 * mu * mu * mum1 * p3.x + mu3 * p4.x;
p.y = mum13 * p1.y + 3 * mu * mum1 * mum1 * p2.y + 3 * mu * mu * mum1 * p3.y + mu3 * p4.y;
//p.z = mum13*p1.z + 3*mu*mum1*mum1*p2.z + 3*mu*mu*mum1*p3.z + mu3*p4.z;
return (p);
}
/**
* from geodroid
* FIXME
*/
public static List<Point> cubicSplineControlPoints(Point[] coords, float alpha) {
if (alpha < 0.0 || alpha > 1.0) {
throw new IllegalArgumentException("alpha must be between 0 and 1 inclusive");
}
if (coords.length < 2) {
throw new IllegalArgumentException("number of Points must be >= 2");
}
int n = coords.length;
List<Point> ctrl = new ArrayList<Point>();
Point curr = new Point(2 * coords[0].x - coords[1].x, 2 * coords[0].y - coords[1].y);
Point next = coords[0];
Point mid = new Point();
mid.x = (curr.x + next.x) / 2.0;
mid.y = (curr.y + next.y) / 2.0;
Point midPrev = new Point();
Point last = new Point(2 * coords[n - 1].x - coords[n - 2].x,
2 * coords[n - 1].y - coords[n - 2].y);
Point anchor = new Point();
double dv = curr.distance(next);
for (int i = 0; i < n; i++) {
curr = next;
next = i < n - 1 ? coords[i + 1] : last;
midPrev.x = mid.x;
midPrev.y = mid.y;
mid.x = (curr.x + next.x) / 2.0;
mid.y = (curr.y + next.y) / 2.0;
double dvPrev = dv;
dv = curr.distance(next);
double p = dvPrev / (dvPrev + dv);
anchor.x = midPrev.x + p * (mid.x - midPrev.x);
anchor.y = midPrev.y + p * (mid.y - midPrev.y);
double dx = anchor.x - curr.x;
double dy = anchor.y - curr.y;
if (i > 0) {
ctrl.add(new Point(alpha * (curr.x - midPrev.x + dx) + midPrev.x - dx,
alpha * (curr.y - midPrev.y + dy) + midPrev.y - dy));
}
if (i < n - 1) {
ctrl.add(new Point(alpha * (curr.x - mid.x + dx) + mid.x - dx,
alpha * (curr.y - mid.y + dy) + mid.y - dy));
}
}
return ctrl;
}
}