android画经过多点的曲线

转载地址


android自带的画曲线方法是不经过控制点的,而有时候又有这样的需要, 网上找了很多资料,是用三次函数实现的.

步骤是大概这样的

  1. 获取经过多点的函数曲线
  2. 在函数曲线上平均获取一些点,画短直线

具体实现不清楚,一句话

I do not know why, but it works.

代码如下

package com.example.pj011_cubics.view.entry;

/** this class represents a cubic polynomial */

public class Cubic {

  float a,b,c,d;         /* a + b*u + c*u^2 +d*u^3 */

  public Cubic(float a, float b, float c, float d){
    this.a = a;
    this.b = b;
    this.c = c;
    this.d = d;
  }

  
  /** evaluate cubic */
  public float eval(float u) {
    return (((d*u) + c)*u + b)*u + a;
  }
}
<pre name="code" class="java">/**
 * 
 */
package com.example.pj011_cubics.view;

import java.util.LinkedList;
import java.util.List;

import com.example.pj011_cubics.view.entry.Cubic;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
 * 画图用View·
 * @author 113108A006FEU
 *
 */
public class MyView extends View {
	/**
	 * 重要参数,两点之间分为几段描画,数字愈大分段越多,描画的曲线就越精细.
	 */
	private static final int STEPS = 12;
	Paint paint;
	Path linePath;
	Path curvePath;
	List<Point> points;
	List<Integer> points_x;
	List<Integer> points_y;

	boolean drawLineFlag;
	boolean drawCurveFlag;

	/**
	 * struct.
	 * 
	 * @param context
	 */
	public MyView(Context context) {
		super(context);
		initObj();
	}

	/**
	 * struct.
	 * 
	 * @param context
	 * @param attrs
	 */
	public MyView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initObj();
	}

	/**
	 * struct.
	 * 
	 * @param context
	 * @param attrs
	 * @param defStyle
	 */
	public MyView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initObj();
	}

	/**
	 * 计算曲线.
	 * 
	 * @param x
	 * @return
	 */
	private List<Cubic> calculate(List<Integer> x) {
		int n = x.size() - 1;
		float[] gamma = new float[n + 1];
		float[] delta = new float[n + 1];
		float[] D = new float[n + 1];
		int i;
		/*
		 * We solve the equation [2 1 ] [D[0]] [3(x[1] - x[0]) ] |1 4 1 | |D[1]|
		 * |3(x[2] - x[0]) | | 1 4 1 | | . | = | . | | ..... | | . | | . | | 1 4
		 * 1| | . | |3(x[n] - x[n-2])| [ 1 2] [D[n]] [3(x[n] - x[n-1])]
		 * 
		 * by using row operations to convert the matrix to upper triangular and
		 * then back sustitution. The D[i] are the derivatives at the knots.
		 */

		gamma[0] = 1.0f / 2.0f;
		for (i = 1; i < n; i++) {
			gamma[i] = 1 / (4 - gamma[i - 1]);
		}
		gamma[n] = 1 / (2 - gamma[n - 1]);

		delta[0] = 3 * (x.get(1) - x.get(0)) * gamma[0];
		for (i = 1; i < n; i++) {
			delta[i] = (3 * (x.get(i + 1) - x.get(i - 1)) - delta[i - 1])
					* gamma[i];
		}
		delta[n] = (3 * (x.get(n) - x.get(n - 1)) - delta[n - 1]) * gamma[n];

		D[n] = delta[n];
		for (i = n - 1; i >= 0; i--) {
			D[i] = delta[i] - gamma[i] * D[i + 1];
		}

		/* now compute the coefficients of the cubics */
		List<Cubic> cubics = new LinkedList<Cubic>();
		for (i = 0; i < n; i++) {
			Cubic c = new Cubic(x.get(i), D[i], 3 * (x.get(i + 1) - x.get(i))
					- 2 * D[i] - D[i + 1], 2 * (x.get(i) - x.get(i + 1)) + D[i]
					+ D[i + 1]);
			cubics.add(c);
		}
		return cubics;
	}

	/**
	 * 清除屏幕上的点.
	 */
	public void clearPoints() {
		points.clear();
		invalidate();
	}

	/**
	 * 画曲线.
	 * 
	 * @param canvas
	 */
	private void drawCurve(Canvas canvas) {
		paint.setColor(Color.RED);
		points_x.clear();
		points_y.clear();
		for (int i = 0; i < points.size(); i++) {
			points_x.add(points.get(i).x);
			points_y.add(points.get(i).y);
		}

		List<Cubic> calculate_x = calculate(points_x);
		List<Cubic> calculate_y = calculate(points_y);
		curvePath
				.moveTo(calculate_x.get(0).eval(0), calculate_y.get(0).eval(0));

		for (int i = 0; i < calculate_x.size(); i++) {
			for (int j = 1; j <= STEPS; j++) {
				float u = j / (float) STEPS;
				curvePath.lineTo(calculate_x.get(i).eval(u), calculate_y.get(i)
						.eval(u));
			}
		}
		canvas.drawPath(curvePath, paint);
	}

	/**
	 * 画点.
	 * 
	 * @param canvas
	 */
	private void drawPoints(Canvas canvas) {
		for (int i = 0; i < points.size(); i++) {
			Point p = points.get(i);
			canvas.drawCircle(p.x, p.y, 5, paint);
		}
	}

	/**
	 * 初始化.
	 */
	private void initObj() {
		paint = new Paint();
		linePath = new Path();
		curvePath = new Path();
		points = new LinkedList<Point>();
		points_x = new LinkedList<Integer>();
		points_y = new LinkedList<Integer>();
		drawLineFlag = true;
		drawCurveFlag = true;
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		paint.setAntiAlias(true);
		paint.setColor(Color.BLUE);
		paint.setStyle(Paint.Style.STROKE);
		paint.setStrokeWidth(5);

		drawPoints(canvas);

		linePath.reset();
		curvePath.reset();

		if (drawLineFlag && points.size() > 1) {
			paint.setColor(Color.GREEN);
			linePath.moveTo(points.get(0).x, points.get(0).y);
			for (int i = 1; i < points.size(); i++) {
				linePath.lineTo(points.get(i).x, points.get(i).y);
			}
			canvas.drawPath(linePath, paint);
		}

		if (points.size() > 2) {
			drawCurve(canvas);
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {

		points.add(new Point((int) event.getX(), (int) event.getY()));
		invalidate();
		return super.onTouchEvent(event);
	}
}
package com.example.pj011_cubics;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.example.pj011_cubics.view.MyView;

public class MainActivity extends Activity {
	private MyView canvasView;
	private Button btnClearPoints;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		getViews();
		btnClearPoints.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				canvasView.clearPoints();
			}
		});
	}

	private void getViews() {
		canvasView = (MyView) findViewById(R.id.canvasView);
		btnClearPoints = (Button) findViewById(R.id.btnClearPoints);
	}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <com.example.pj011_cubics.view.MyView
        android:id="@+id/canvasView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <Button
        android:id="@+id/btnClearPoints"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/canvasView"
        android:layout_alignTop="@+id/canvasView"
        android:text="ClearPoints" />

</RelativeLayout>




 


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值