add BezierPath utility
This commit is contained in:
parent
bbaa19ef7b
commit
842d20cf7b
73
vtm/src/org/oscim/renderer/test/BezierPathLayer.java
Normal file
73
vtm/src/org/oscim/renderer/test/BezierPathLayer.java
Normal file
@ -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<Point> 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();
|
||||
}
|
||||
}
|
||||
}
|
115
vtm/src/org/oscim/utils/math/BezierPath.java
Normal file
115
vtm/src/org/oscim/utils/math/BezierPath.java
Normal file
@ -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<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;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user