2014-03-31 18 views
3

我有2d個點的數組,我需要創建一個穿過所有點的Path。我想我應該使用​​方法,它使用指定的控制點在兩點之間創建貝塞爾曲線。問題是我不知道我的曲線的控制點。我如何計算它們?使用android.graphics.Path構造樣條

也許有更好的方法來做到這一點?也許有某種圖書館可以幫助我?

回答

1

在我讀了this文章後,它變得很簡單。

這就是你如何在android上做到這一點。運行此代碼後,您的路徑p將會穿過knotsArr陣列中的所有點。

Point[] knotsArr = {new Point(0, 0), 
        new Point(5, 5), 
        new Point(10, 0), 
        new Point(15, 5)}; 
Point[][] controlPoints = BezierSplineUtil.getCurveControlPoints(knotsArr); 
Point[] firstCP = controlPoints[0]; 
Point[] secondCP = controlPoints[1]; 

Path p = new Path(); 
p.moveTo(knots.get(0).x, knots.get(0).y); 

for (int i = 0; i < firstCP.length; i++) { 
    p.cubicTo(firstCP[i].x, firstCP[i].y, 
       secondCP[i].x, secondCP[i].y, 
       knots.get(i + 1).x, knots.get(i + 1).y); 
} 

BezierSplineUtil.java

public class BezierSplineUtil { 

    public static class Point { 

     public final float x; 
     public final float y; 

     public Point(float x, float y) { 
      this.x = x; 
      this.y = y; 
     } 

    } 

    /** 
    * Get open-ended bezier spline control points. 
    * 
    * @param knots bezier spline points. 
    * @return [2 x knots.length - 1] matrix. First row of the matrix = first 
    *   control points. Second row of the matrix = second control points. 
    * @throws IllegalArgumentException if less than two knots are passed. 
    */ 
    public static Point[][] getCurveControlPoints(Point[] knots) { 
     if (knots == null || knots.length < 2) { 
      throw new IllegalArgumentException("At least two knot points are required"); 
     } 

     final int n = knots.length - 1; 
     final Point[] firstControlPoints = new Point[n]; 
     final Point[] secondControlPoints = new Point[n]; 

     // Special case: bezier curve should be a straight line 
     if (n == 1) { 
      // 3P1 = 2P0 + P3 
      float x = (2 * knots[0].x + knots[1].x)/3; 
      float y = (2 * knots[0].y + knots[1].y)/3; 
      firstControlPoints[0] = new Point(x, y); 

      // P2 = 2P1 - P0 
      x = 2 * firstControlPoints[0].x - knots[0].x; 
      y = 2 * firstControlPoints[0].y - knots[0].y; 
      secondControlPoints[0] = new Point(x, y); 

      return new Point[][] { firstControlPoints, secondControlPoints }; 
     } 

     // Calculate first bezier control points 
     // Right hand side vector 
     float[] rhs = new float[n]; 

     // Set right hand side X values 
     for (int i = 1; i < n - 1; i++) { 
      rhs[i] = 4 * knots[i].x + 2 * knots[i + 1].x; 
     } 
     rhs[0] = knots[0].x + 2 * knots[1].x; 
     rhs[n - 1] = (8 * knots[n - 1].x + knots[n].x)/2f; 

     // Get first control points X-values 
     float[] x = getFirstControlPoints(rhs); 

     // Set right hand side Y values 
     for (int i = 1; i < n - 1; i++) { 
      rhs[i] = 4 * knots[i].y + 2 * knots[i + 1].y; 
     } 
     rhs[0] = knots[0].y + 2 * knots[1].y; 
     rhs[n - 1] = (8 * knots[n - 1].y + knots[n].y)/2f; 

     // Get first control points Y-values 
     float[] y = getFirstControlPoints(rhs); 

     for (int i = 0; i < n; i++) { 
      // First control point 
      firstControlPoints[i] = new Point(x[i], y[i]); 

      // Second control point 
      if (i < n - 1) { 
       float xx = 2 * knots[i + 1].x - x[i + 1]; 
       float yy = 2 * knots[i + 1].y - y[i + 1]; 
       secondControlPoints[i] = new Point(xx, yy); 
      } else { 
       float xx = (knots[n].x + x[n - 1])/2; 
       float yy = (knots[n].y + y[n - 1])/2; 
       secondControlPoints[i] = new Point(xx, yy); 
      } 
     } 

     return new Point[][] { firstControlPoints, secondControlPoints }; 
    } 

    /** 
    * Solves a tridiagonal system for one of coordinates (x or y) of first 
    * bezier control points. 
    * 
    * @param rhs right hand side vector. 
    * @return Solution vector. 
    */ 
    private static float[] getFirstControlPoints(float[] rhs) { 
     int n = rhs.length; 
     float[] x = new float[n]; // Solution vector 
     float[] tmp = new float[n]; // Temp workspace 

     float b = 2.0f; 
     x[0] = rhs[0]/b; 

     // Decomposition and forward substitution 
     for (int i = 1; i < n; i++) { 
      tmp[i] = 1/b; 
      b = (i < n - 1 ? 4.0f : 3.5f) - tmp[i]; 
      x[i] = (rhs[i] - x[i - 1])/b; 
     } 

     // Backsubstitution 
     for (int i = 1; i < n; i++) { 
      x[n - i - 1] -= tmp[n - i] * x[n - i]; 
     } 

     return x; 
    } 

}