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; } }