diff --git a/vtm/src/org/oscim/renderer/test/BezierPathLayer.java b/vtm/src/org/oscim/renderer/test/BezierPathLayer.java new file mode 100644 index 00000000..7d2ef109 --- /dev/null +++ b/vtm/src/org/oscim/renderer/test/BezierPathLayer.java @@ -0,0 +1,73 @@ +package org.oscim.renderer.test; + +import java.util.List; + +import org.oscim.backend.canvas.Color; +import org.oscim.core.GeometryBuffer; +import org.oscim.core.MapPosition; +import org.oscim.core.Point; +import org.oscim.renderer.ElementRenderer; +import org.oscim.renderer.MapRenderer.Matrices; +import org.oscim.renderer.elements.LineLayer; +import org.oscim.theme.styles.Line; +import org.oscim.utils.math.BezierPath; + +public class BezierPathLayer extends ElementRenderer { + + public BezierPathLayer() { + mMapPosition.scale = 0; + + GeometryBuffer g = new GeometryBuffer(100, 1); + g.startLine(); + + Point[] pts = new Point[10]; + for (int i = 0; i < 10; i++) { + pts[i] = new Point(i * 3, (i * i) % 3 * 4); + pts[i].x *= 10; + pts[i].y *= 10; + // System.out.println(pts[i]); + g.addPoint(pts[i]); + } + LineLayer ll = layers.addLineLayer(0, new Line(Color.BLUE, 2f)); + ll.addLine(g); + + List ctrl = BezierPath.cubicSplineControlPoints(pts, 0.1f); + + g.clear(); + g.startLine(); + Point p0 = pts[0]; + + for (int j = 1, k = 0; j < pts.length; j++) { + Point p1 = ctrl.get(k++); + Point p2 = ctrl.get(k++); + Point p3 = pts[j]; + System.out.println(">>> " + p1 + " " + p2); + for (int i = 0; i < 10; i++) { + double mu = (i / 10f); + Point p = BezierPath.cubicBezier(p0, p1, p2, p3, mu); + g.addPoint(p); + System.out.println(mu + " " + p); + } + p0 = p3; + } + ll = layers.addLineLayer(1, new Line(Color.CYAN, 2f)); + ll.addLine(g); + + } + + public synchronized void clear() { + layers.clear(); + setReady(false); + } + + @Override + protected synchronized void update(MapPosition pos, boolean changed, Matrices m) { + + if (mMapPosition.scale == 0) + mMapPosition.copy(pos); + + if (!isReady()) { + compile(); + } + } +} diff --git a/vtm/src/org/oscim/utils/math/BezierPath.java b/vtm/src/org/oscim/utils/math/BezierPath.java new file mode 100644 index 00000000..792d7e8e --- /dev/null +++ b/vtm/src/org/oscim/utils/math/BezierPath.java @@ -0,0 +1,115 @@ +package org.oscim.utils.math; + +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 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 ctrl = new ArrayList(); + + 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; + } +}