Update vector
This commit is contained in:
1 parent
be9d051d39
commit
de7a5b6395
3 files changed
+670
-631
No files matched your search
@@ -24,9 +24,8 @@ import android.view.InflateException;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import com.hippo.graphics.JPath;
|
||||
import com.hippo.util.JPathParser;
|
||||
|
||||
/**
|
||||
* An interpolator that can traverse a Path that extends from <code>Point</code>
|
||||
@@ -59,7 +58,7 @@ public class PathInterpolator implements Interpolator {
|
||||
*
|
||||
* @param path The <code>Path</code> to use to make the line representing the interpolator.
|
||||
*/
|
||||
public PathInterpolator(Path path) {
|
||||
public PathInterpolator(JPath path) {
|
||||
initPath(path);
|
||||
}
|
||||
|
||||
@@ -109,7 +108,7 @@ public class PathInterpolator implements Interpolator {
|
||||
// will be all coming from pathData.
|
||||
if (a.hasValue(R.styleable.PathInterpolator_pathData)) {
|
||||
String pathData = a.getString(R.styleable.PathInterpolator_pathData);
|
||||
Path path = IpPathParser.createPathFromPathData(pathData);
|
||||
JPath path = JPathParser.createPathFromPathData(pathData);
|
||||
if (path == null) {
|
||||
throw new InflateException("The path is null, which is created"
|
||||
+ " from " + pathData);
|
||||
@@ -143,20 +142,20 @@ public class PathInterpolator implements Interpolator {
|
||||
}
|
||||
|
||||
private void initQuad(float controlX, float controlY) {
|
||||
Path path = new Path();
|
||||
JPath path = new JPath();
|
||||
path.moveTo(0, 0);
|
||||
path.quadTo(controlX, controlY, 1f, 1f);
|
||||
initPath(path);
|
||||
}
|
||||
|
||||
private void initCubic(float x1, float y1, float x2, float y2) {
|
||||
Path path = new Path();
|
||||
JPath path = new JPath();
|
||||
path.moveTo(0, 0);
|
||||
path.cubicTo(x1, y1, x2, y2, 1f, 1f);
|
||||
initPath(path);
|
||||
}
|
||||
|
||||
private void initPath(Path path) {
|
||||
private void initPath(JPath path) {
|
||||
float[] pointComponents = path.approximate(PRECISION);
|
||||
|
||||
int numPoints = pointComponents.length / 3;
|
||||
@@ -231,609 +230,4 @@ public class PathInterpolator implements Interpolator {
|
||||
float endY = mY[endIndex];
|
||||
return startY + (fraction * (endY - startY));
|
||||
}
|
||||
|
||||
private static final class PointMap {
|
||||
|
||||
private int size = 0;
|
||||
|
||||
private Link firstLink;
|
||||
private Link lastLink;
|
||||
|
||||
float totalLength = 0f;
|
||||
|
||||
private static final class Link {
|
||||
/** It is only for bezier **/
|
||||
float t;
|
||||
float x;
|
||||
float y;
|
||||
/** It should be Length first **/
|
||||
float f = -1;
|
||||
|
||||
private Link previous, next;
|
||||
|
||||
Link(float t, float x, float y, float f, Link p, Link n) {
|
||||
this.t = t;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.f = f;
|
||||
this.previous = p;
|
||||
this.next = n;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Iterator {
|
||||
|
||||
final PointMap parent;
|
||||
Link link;
|
||||
|
||||
private Iterator(PointMap p, Link l) {
|
||||
parent = p;
|
||||
link = l;
|
||||
}
|
||||
|
||||
boolean hasNext() {
|
||||
return link.next != null;
|
||||
}
|
||||
|
||||
Iterator nextIterator() {
|
||||
if (hasNext()) {
|
||||
return new Iterator(parent, link.next);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Move iterator to the new data
|
||||
void addBefore(float t, float x, float y, float f) {
|
||||
Link p = link.previous;
|
||||
Link l = new Link(t, x, y, f, p, link);
|
||||
link.previous = l;
|
||||
p.next = l;
|
||||
link = l;
|
||||
parent.size++;
|
||||
}
|
||||
}
|
||||
|
||||
public void add(float t, float x, float y, float f) {
|
||||
Link link = new Link(t, x, y, f, null, null);
|
||||
if (lastLink != null) {
|
||||
link.previous = lastLink;
|
||||
lastLink.next = link;
|
||||
}
|
||||
lastLink = link;
|
||||
if (firstLink == null) {
|
||||
firstLink = link;
|
||||
}
|
||||
size++;
|
||||
}
|
||||
|
||||
// Get a iterator at first data or null
|
||||
public Iterator iterator() {
|
||||
if (firstLink != null) {
|
||||
return new Iterator(this, firstLink);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator lastIterator() {
|
||||
if (lastLink != null) {
|
||||
return new Iterator(this, lastLink);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public float[] generate() {
|
||||
int index = 0;
|
||||
float[] result = new float[size * 3];
|
||||
for (Link link = firstLink; link != null; link = link.next) {
|
||||
result[index++] = link.f / totalLength;
|
||||
result[index++] = link.x;
|
||||
result[index++] = link.y;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Path {
|
||||
|
||||
private List<PathAction> mActionList = new LinkedList<>();
|
||||
|
||||
/** startX, startY, length**/
|
||||
private float[] mTemp = new float[2];
|
||||
|
||||
{
|
||||
mTemp[0] = 0f;
|
||||
mTemp[1] = 0f;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
// Empty
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the beginning of the next contour to the point (x,y).
|
||||
*
|
||||
* @param x The x-coordinate of the start of a new contour
|
||||
* @param y The y-coordinate of the start of a new contour
|
||||
*/
|
||||
public void moveTo(float x, float y) {
|
||||
mActionList.add(new MoveAction(x, y));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the beginning of the next contour relative to the last point on the
|
||||
* previous contour. If there is no previous contour, this is treated the
|
||||
* same as moveTo().
|
||||
*
|
||||
* @param dx The amount to add to the x-coordinate of the end of the
|
||||
* previous contour, to specify the start of a new contour
|
||||
* @param dy The amount to add to the y-coordinate of the end of the
|
||||
* previous contour, to specify the start of a new contour
|
||||
*/
|
||||
public void rMoveTo(float dx, float dy) {
|
||||
mActionList.add(new RMoveAction(dx, dy));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a line from the last point to the specified point (x,y).
|
||||
* If no moveTo() call has been made for this contour, the first point is
|
||||
* automatically set to (0,0).
|
||||
*
|
||||
* @param x The x-coordinate of the end of a line
|
||||
* @param y The y-coordinate of the end of a line
|
||||
*/
|
||||
public void lineTo(float x, float y) {
|
||||
mActionList.add(new LineToAction(x, y));
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as lineTo, but the coordinates are considered relative to the last
|
||||
* point on this contour. If there is no previous point, then a moveTo(0,0)
|
||||
* is inserted automatically.
|
||||
*
|
||||
* @param dx The amount to add to the x-coordinate of the previous point on
|
||||
* this contour, to specify a line
|
||||
* @param dy The amount to add to the y-coordinate of the previous point on
|
||||
* this contour, to specify a line
|
||||
*/
|
||||
public void rLineTo(float dx, float dy) {
|
||||
mActionList.add(new RLineToAction(dx, dy));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a quadratic bezier from the last point, approaching control point
|
||||
* (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
|
||||
* this contour, the first point is automatically set to (0,0).
|
||||
*
|
||||
* @param x1 The x-coordinate of the control point on a quadratic curve
|
||||
* @param y1 The y-coordinate of the control point on a quadratic curve
|
||||
* @param x2 The x-coordinate of the end point on a quadratic curve
|
||||
* @param y2 The y-coordinate of the end point on a quadratic curve
|
||||
*/
|
||||
public void quadTo(float x1, float y1, float x2, float y2) {
|
||||
mActionList.add(new QuadToAction(x1, y1, x2, y2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as quadTo, but the coordinates are considered relative to the last
|
||||
* point on this contour. If there is no previous point, then a moveTo(0,0)
|
||||
* is inserted automatically.
|
||||
*
|
||||
* @param dx1 The amount to add to the x-coordinate of the last point on
|
||||
* this contour, for the control point of a quadratic curve
|
||||
* @param dy1 The amount to add to the y-coordinate of the last point on
|
||||
* this contour, for the control point of a quadratic curve
|
||||
* @param dx2 The amount to add to the x-coordinate of the last point on
|
||||
* this contour, for the end point of a quadratic curve
|
||||
* @param dy2 The amount to add to the y-coordinate of the last point on
|
||||
* this contour, for the end point of a quadratic curve
|
||||
*/
|
||||
public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
|
||||
mActionList.add(new RQuadToAction(dx1, dy1, dx2, dy2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a cubic bezier from the last point, approaching control points
|
||||
* (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
|
||||
* made for this contour, the first point is automatically set to (0,0).
|
||||
*
|
||||
* @param x1 The x-coordinate of the 1st control point on a cubic curve
|
||||
* @param y1 The y-coordinate of the 1st control point on a cubic curve
|
||||
* @param x2 The x-coordinate of the 2nd control point on a cubic curve
|
||||
* @param y2 The y-coordinate of the 2nd control point on a cubic curve
|
||||
* @param x3 The x-coordinate of the end point on a cubic curve
|
||||
* @param y3 The y-coordinate of the end point on a cubic curve
|
||||
*/
|
||||
public void cubicTo(float x1, float y1, float x2, float y2,
|
||||
float x3, float y3) {
|
||||
mActionList.add(new CubicToAction(x1, y1, x2, y2, x3, y3));
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as cubicTo, but the coordinates are considered relative to the
|
||||
* current point on this contour. If there is no previous point, then a
|
||||
* moveTo(0,0) is inserted automatically.
|
||||
*/
|
||||
public void rCubicTo(float x1, float y1, float x2, float y2,
|
||||
float x3, float y3) {
|
||||
mActionList.add(new RCubicToAction(x1, y1, x2, y2, x3, y3));
|
||||
}
|
||||
|
||||
/**
|
||||
* Approximate the <code>Path</code> with a series of line segments.
|
||||
* This returns float[] with the array containing point components.
|
||||
* There are three components for each point, in order:
|
||||
* <ul>
|
||||
* <li>Fraction along the length of the path that the point resides</li>
|
||||
* <li>The x coordinate of the point</li>
|
||||
* <li>The y coordinate of the point</li>
|
||||
* </ul>
|
||||
* <p>Two points may share the same fraction along its length when there is
|
||||
* a move action within the Path.</p>
|
||||
*
|
||||
* @param acceptableError The acceptable error for a line on the
|
||||
* Path. Typically this would be 0.5 so that
|
||||
* the error is less than half a pixel.
|
||||
* @return An array of components for points approximating the Path.
|
||||
*/
|
||||
public float[] approximate(float acceptableError) {
|
||||
PointMap pm = new PointMap();
|
||||
for (PathAction pa : mActionList) {
|
||||
pa.approximate(pm, mTemp, acceptableError);
|
||||
}
|
||||
return pm.generate();
|
||||
}
|
||||
}
|
||||
|
||||
private abstract static class PathAction {
|
||||
public abstract void approximate(PointMap pointMap, float[] startPoint, float acceptableError);
|
||||
}
|
||||
|
||||
private static class MoveAction extends PathAction {
|
||||
|
||||
private float mX;
|
||||
private float mY;
|
||||
|
||||
public MoveAction(float x, float y) {
|
||||
mX = x;
|
||||
mY = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void approximate(PointMap pointMap, float[] startPoint, float acceptableError) {
|
||||
float x = mX;
|
||||
float y = mY;
|
||||
pointMap.add(0f, x, y, pointMap.totalLength);
|
||||
startPoint[0] = x;
|
||||
startPoint[1] = y;
|
||||
}
|
||||
}
|
||||
|
||||
private static class RMoveAction extends PathAction {
|
||||
|
||||
private float mDx;
|
||||
private float mDy;
|
||||
|
||||
public RMoveAction(float dx, float dy) {
|
||||
mDx = dx;
|
||||
mDy = dy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void approximate(PointMap pointMap, float[] startPoint, float acceptableError) {
|
||||
float x = startPoint[0] + mDx;
|
||||
float y = startPoint[1] + mDy;
|
||||
pointMap.add(0f, x, y, pointMap.totalLength);
|
||||
startPoint[0] = x;
|
||||
startPoint[1] = y;
|
||||
}
|
||||
}
|
||||
|
||||
private static class LineToAction extends PathAction {
|
||||
|
||||
private float mX;
|
||||
private float mY;
|
||||
|
||||
public LineToAction(float x, float y) {
|
||||
mX = x;
|
||||
mY = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void approximate(PointMap pointMap, float[] startPoint, float acceptableError) {
|
||||
if (pointMap.size == 0) {
|
||||
// No start point in map, just add it
|
||||
pointMap.add(0f, startPoint[0], startPoint[1], 0f);
|
||||
}
|
||||
|
||||
float x = mX;
|
||||
float y = mY;
|
||||
float length = dist(startPoint[0], startPoint[1], x, y) +
|
||||
pointMap.totalLength;
|
||||
pointMap.add(0f, x, y, length);
|
||||
pointMap.totalLength = length;
|
||||
startPoint[0] = x;
|
||||
startPoint[1] = y;
|
||||
}
|
||||
}
|
||||
|
||||
private static class RLineToAction extends PathAction {
|
||||
|
||||
private float mDx;
|
||||
private float mDy;
|
||||
|
||||
public RLineToAction(float dx, float dy) {
|
||||
mDx = dx;
|
||||
mDy = dy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void approximate(PointMap pointMap, float[] startPoint, float acceptableError) {
|
||||
if (pointMap.size == 0) {
|
||||
// No start point in map, just add it
|
||||
pointMap.add(0f, startPoint[0], startPoint[1], 0f);
|
||||
}
|
||||
|
||||
float x = startPoint[0] + mDx;
|
||||
float y = startPoint[1] + mDy;
|
||||
float length = (float) Math.hypot(mDx, mDy) +
|
||||
pointMap.totalLength;
|
||||
pointMap.add(0f, x, y, length);
|
||||
pointMap.totalLength = length;
|
||||
startPoint[0] = x;
|
||||
startPoint[1] = y;
|
||||
}
|
||||
}
|
||||
|
||||
private static class QuadToAction extends PathAction {
|
||||
|
||||
private float mX1;
|
||||
private float mY1;
|
||||
private float mX2;
|
||||
private float mY2;
|
||||
|
||||
public QuadToAction(float x1, float y1, float x2, float y2) {
|
||||
mX1 = x1;
|
||||
mY1 = y1;
|
||||
mX2 = x2;
|
||||
mY2 = y2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void approximate(PointMap pointMap, float[] startPoint, float acceptableError) {
|
||||
float[] control = new float[]{
|
||||
startPoint[0], startPoint[1],
|
||||
mX1, mY1,
|
||||
mX2, mY2
|
||||
};
|
||||
bezierApproximate(pointMap, control, acceptableError, false);
|
||||
startPoint[0] = control[0];
|
||||
startPoint[1] = control[1];
|
||||
}
|
||||
}
|
||||
|
||||
private static class RQuadToAction extends PathAction {
|
||||
|
||||
private float mDx1;
|
||||
private float mDy1;
|
||||
private float mDx2;
|
||||
private float mDy2;
|
||||
|
||||
public RQuadToAction(float dx1, float dy1, float dx2, float dy2) {
|
||||
mDx1 = dx1;
|
||||
mDy1 = dy1;
|
||||
mDx2 = dx2;
|
||||
mDy2 = dy2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void approximate(PointMap pointMap, float[] startPoint, float acceptableError) {
|
||||
float startX = startPoint[0];
|
||||
float startY = startPoint[1];
|
||||
float[] control = new float[]{
|
||||
startX, startY,
|
||||
startX + mDx1, startY + mDy1,
|
||||
startX + mDx2, startY + mDy2
|
||||
};
|
||||
bezierApproximate(pointMap, control, acceptableError, false);
|
||||
startPoint[0] = control[0];
|
||||
startPoint[1] = control[1];
|
||||
}
|
||||
}
|
||||
|
||||
private static class CubicToAction extends PathAction {
|
||||
|
||||
private float mX1;
|
||||
private float mY1;
|
||||
private float mX2;
|
||||
private float mY2;
|
||||
private float mX3;
|
||||
private float mY3;
|
||||
|
||||
public CubicToAction(float x1, float y1, float x2, float y2, float x3, float y3) {
|
||||
mX1 = x1;
|
||||
mY1 = y1;
|
||||
mX2 = x2;
|
||||
mY2 = y2;
|
||||
mX3 = x3;
|
||||
mY3 = y3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void approximate(PointMap pointMap, float[] startPoint, float acceptableError) {
|
||||
float[] control = new float[]{
|
||||
startPoint[0], startPoint[1],
|
||||
mX1, mY1,
|
||||
mX2, mY2,
|
||||
mX3, mY3
|
||||
};
|
||||
bezierApproximate(pointMap, control, acceptableError, true);
|
||||
startPoint[0] = control[0];
|
||||
startPoint[1] = control[1];
|
||||
}
|
||||
}
|
||||
|
||||
private static class RCubicToAction extends PathAction {
|
||||
|
||||
private float mDx1;
|
||||
private float mDy1;
|
||||
private float mDx2;
|
||||
private float mDy2;
|
||||
private float mDx3;
|
||||
private float mDy3;
|
||||
|
||||
public RCubicToAction(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) {
|
||||
mDx1 = dx1;
|
||||
mDy1 = dy1;
|
||||
mDx2 = dx2;
|
||||
mDy2 = dy2;
|
||||
mDx3 = dx3;
|
||||
mDy3 = dy3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void approximate(PointMap pointMap, float[] startPoint, float acceptableError) {
|
||||
float startX = startPoint[0];
|
||||
float startY = startPoint[1];
|
||||
float[] control = new float[]{
|
||||
startX, startY,
|
||||
startX + mDx1, startY + mDy1,
|
||||
startX + mDx2, startY + mDy2,
|
||||
startX + mDx3, startY + mDy3,
|
||||
};
|
||||
bezierApproximate(pointMap, control, acceptableError, true);
|
||||
startPoint[0] = control[0];
|
||||
startPoint[1] = control[1];
|
||||
}
|
||||
}
|
||||
|
||||
// Divides Bezier curves until linear interpolation is very close to accurate, using
|
||||
// errorSquared as a metric. Cubic Bezier curves can have an inflection point that improperly
|
||||
// short-circuit subdivision. If you imagine an S shape, the top and bottom points being the
|
||||
// starting and end points, linear interpolation would mark the center where the curve places
|
||||
// the point. It is clearly not the case that we can linearly interpolate at that point.
|
||||
// doubleCheckDivision forces a second examination between subdivisions to ensure that linear
|
||||
// interpolation works.
|
||||
private static void bezierApproximate(PointMap pointMap, float[] control,
|
||||
float acceptableError, boolean isCubic) {
|
||||
float errorSquared = acceptableError * acceptableError;
|
||||
|
||||
if (pointMap.size == 0) {
|
||||
// No start point in map, just add it
|
||||
pointMap.add(0f, control[0], control[1], 0f);
|
||||
}
|
||||
|
||||
PointMap.Iterator iter = pointMap.lastIterator();
|
||||
// Make sure start t is 0
|
||||
iter.link.t = 0f;
|
||||
|
||||
// Add end point
|
||||
if (isCubic) {
|
||||
pointMap.add(1f, control[6], control[7], 0);
|
||||
} else {
|
||||
pointMap.add(1f, control[4], control[5], 0);
|
||||
}
|
||||
|
||||
// Get next iterator
|
||||
PointMap.Iterator next = iter.nextIterator();
|
||||
|
||||
boolean doubleCheckDivision = isCubic;
|
||||
while (next != null) {
|
||||
boolean needsSubdivision;
|
||||
|
||||
do {
|
||||
PointMap.Link iterLink = iter.link;
|
||||
PointMap.Link nextLink = next.link;
|
||||
|
||||
float midT = (iterLink.t + nextLink.t) / 2;
|
||||
float midX = (iterLink.x + nextLink.x) / 2;
|
||||
float midY = (iterLink.y + nextLink.y) / 2;
|
||||
|
||||
float midPointX = bezierX(midT, control, isCubic);
|
||||
float midPointY = bezierY(midT, control, isCubic);
|
||||
|
||||
needsSubdivision = isOutOfErrorSquared(midX, midY, midPointX, midPointY, errorSquared);
|
||||
|
||||
if (!needsSubdivision && doubleCheckDivision) {
|
||||
float quarterT = (iterLink.t + midT) / 2;
|
||||
float quarterX = (iterLink.x + midPointX) / 2;
|
||||
float quarterY = (iterLink.y + midPointY) / 2;
|
||||
|
||||
float quarterPointX = bezierX(quarterT, control, isCubic);
|
||||
float quarterPointY = bezierY(quarterT, control, isCubic);
|
||||
|
||||
needsSubdivision = isOutOfErrorSquared(quarterX, quarterY, quarterPointX, quarterPointY, errorSquared);
|
||||
if (needsSubdivision) {
|
||||
// Found an inflection point. No need to double-check.
|
||||
doubleCheckDivision = false;
|
||||
}
|
||||
}
|
||||
if (needsSubdivision) {
|
||||
// Add length soon
|
||||
next.addBefore(midT, midPointX, midPointY, 0);
|
||||
} else {
|
||||
float length = dist(iterLink.x, iterLink.y, nextLink.x, nextLink.y);
|
||||
iterLink.f = pointMap.totalLength;
|
||||
pointMap.totalLength += length;
|
||||
}
|
||||
} while (needsSubdivision);
|
||||
|
||||
iter = next;
|
||||
next = next.nextIterator();
|
||||
}
|
||||
|
||||
PointMap.Link iterLink = iter.link;
|
||||
iterLink.f = pointMap.totalLength;
|
||||
control[0] = iterLink.x;
|
||||
control[1] = iterLink.y;
|
||||
}
|
||||
|
||||
private static boolean isOutOfErrorSquared(float midX, float midY,
|
||||
float midPointX, float midPointY, float errorSquared) {
|
||||
float xError = midPointX - midX;
|
||||
float yError = midPointY - midY;
|
||||
float midErrorSquared = (xError * xError) + (yError * yError);
|
||||
return midErrorSquared > errorSquared;
|
||||
}
|
||||
|
||||
private static float bezierX(float t, float[] control, boolean isCubic) {
|
||||
if (isCubic) {
|
||||
return cubicCoordinateCalculation(t, control[0], control[2], control[4], control[6]);
|
||||
} else {
|
||||
return quadraticCoordinateCalculation(t, control[0], control[2], control[4]);
|
||||
}
|
||||
}
|
||||
|
||||
private static float bezierY(float t, float[] control, boolean isCubic) {
|
||||
if (isCubic) {
|
||||
return cubicCoordinateCalculation(t, control[1], control[3], control[5], control[7]);
|
||||
} else {
|
||||
return quadraticCoordinateCalculation(t, control[1], control[3], control[5]);
|
||||
}
|
||||
}
|
||||
|
||||
private static float quadraticCoordinateCalculation(float t, float p0, float p1, float p2) {
|
||||
float oneMinusT = 1 - t;
|
||||
return oneMinusT * ((oneMinusT * p0) + (t * p1)) + t * ((oneMinusT * p1) + (t * p2));
|
||||
}
|
||||
|
||||
private static float cubicCoordinateCalculation(float t, float p0, float p1, float p2, float p3) {
|
||||
float oneMinusT = 1 - t;
|
||||
float oneMinusTSquared = oneMinusT * oneMinusT;
|
||||
float oneMinusTCubed = oneMinusTSquared * oneMinusT;
|
||||
float tSquared = t * t;
|
||||
float tCubed = tSquared * t;
|
||||
return (oneMinusTCubed * p0) + (3 * oneMinusTSquared * t * p1)
|
||||
+ (3 * oneMinusT * tSquared * p2) + (tCubed * p3);
|
||||
}
|
||||
|
||||
public static float dist(float x1, float y1, float x2, float y2) {
|
||||
final float x = (x2 - x1);
|
||||
final float y = (y2 - y1);
|
||||
return (float) Math.hypot(x, y);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user