1、貝塞爾曲線:http://baike.baidu.com/view/60154.htm,在這里理解什么是貝塞爾曲線
2、直接上圖:
3、100多行代碼就可以畫出貝塞爾曲線,直接上代碼
package com.example.bezier; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PathMeasure; import android.graphics.Paint.Style; import android.graphics.Path; import android.os.Bundle; import android.view.View; import android.view.Window; import android.view.WindowManager; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(new BezierView(this)); } } class BezierView extends View { /** * * @author liqiongwei * @param context * */ public BezierView(Context context) { super(context); } protected void onDraw(Canvas canvas) { List<Float> points = new ArrayList<Float>(); Paint paint = new Paint(); // 添加第一個點(118.0, 294.0), points.add((float) 118.0);// X軸 points.add((float) 294.0);// Y軸 // 添加第二個點 points.add((float) 206.0); points.add((float) 294.0); // 添加第三個點 points.add((float) 294.0); points.add((float) 118.0); // 添加第四個點 points.add((float) 382.0); points.add((float) 206.0); points.add((float) 470.0); points.add((float) 118.0); // 通過畫折線和貝塞爾曲線可以知道,點得位置是不一樣的。 // 畫折線 for (int i = 0; i < points.size() - 2; i = i + 2) { canvas.drawLine(points.get(i), points.get(i + 1), points.get(i + 2), points.get(i + 3), paint); canvas.drawCircle(points.get(i), points.get(i + 1), 3, paint); } canvas.drawCircle(points.get(points.size() - 2), points.get(points.size() - 1), 3, paint); // 貝塞爾曲線 paint.setColor(Color.BLUE); Path p = new Path(); Point p1 = new Point(); Point p2 = new Point(); Point p3 = new Point(); float xp = points.get(0); float yp = points.get(1); // 設置第一個點開始 p.moveTo(xp, yp); int length = points.size(); // 設置第一個控制點33%的距離 float mFirstMultiplier = 0.3f; // 設置第二個控制點為66%的距離 float mSecondMultiplier = 1 - mFirstMultiplier; for (int b = 0; b < length; b += 2) { int nextIndex = b + 2 < length ? b + 2 : b; int nextNextIndex = b + 4 < length ? b + 4 : nextIndex; // 設置第一個控制點 calc(points, p1, b, nextIndex, mSecondMultiplier); // 設置第二個控制點 p2.setX(points.get(nextIndex)); p2.setY(points.get(nextIndex + 1)); // 設置第二個控制點 calc(points, p3, nextIndex, nextNextIndex, mFirstMultiplier); // 最后一個點就是賽貝爾曲線上的點 p.cubicTo(p1.getX(), p1.getY(), p2.getX(), p2.getY(), p3.getX(), p3.getY()); // 畫點 } PathMeasure mPathMeasure; mPathMeasure = new PathMeasure(p, false); // 設置為線 paint.setStyle(Style.STROKE); reSetPointWithPath(mPathMeasure, points); for (int k = 0; k < points.size()-1; k +=2) { canvas.drawCircle(points.get(k), points.get(k+1), 5, paint); } canvas.drawPath(p, paint); invalidate(); } /** * 計算控制點 * @param points * @param result * @param index1 * @param index2 * @param multiplier */ private void calc(List<Float> points, Point result, int index1, int index2, final float multiplier) { float p1x = points.get(index1); float p1y = points.get(index1 + 1); float p2x = points.get(index2); float p2y = points.get(index2 + 1); float diffX = p2x - p1x; float diffY = p2y - p1y; result.setX(p1x + (diffX * multiplier)); result.setY(p1y + (diffY * multiplier)); } /** * 重新設置點的位置,為曲線上的位置 * @param mPathMeasure * @param pointsList */ public void reSetPointWithPath(PathMeasure mPathMeasure, List<Float> pointsList){ int length = (int) mPathMeasure.getLength(); int pointsLength = pointsList.size(); float[] coords = new float[2]; for (int b = 0; b < length; b++) { mPathMeasure.getPosTan(b, coords, null); double prevDiff = Double.MAX_VALUE; boolean ok = true; for (int j = 0; j < pointsLength && ok; j += 2) { double diff = Math.abs(pointsList.get(j) - coords[0]); if (diff < 1) { pointsList.set(j + 1, coords[1]); prevDiff = diff; } ok = prevDiff > diff; } } } }
4、定義點的類
package com.example.bezier; import java.io.Serializable; /** * 點的類,來源於Achartengine */ public final class Point implements Serializable { private float mX; private float mY; public Point() { } public Point(float x, float y) { mX = x; mY = y; } public float getX() { return mX; } public float getY() { return mY; } public void setX(float x) { mX = x; } public void setY(float y) { mY = y; } }
5、下載地址:http://files.cnblogs.com/liqw/Bezier.zip
本文來源於:http://www.cnblogs.com/liqw/p/3631137.html
有問題,請提問,大家一起研究!