android迭代画树

前段时间发现了这个效果;


于是开始了我的迭代之旅,感觉很有目的性!

android用自定义view来处理视图,总体思路就是先画V,画线就需要两个点的坐标,所有主要难的就是求每次画线的点的坐标

1.点分为左点,右点,下面的基点,以及中心线的中点:思路如下,迭代的过程就是先可左侧边的线开始画,然后返回倒数第一个点画右侧,再判断次数是否满足,满足继续画新右侧点的左线,不满足,回到最开始的左线,画倒数第二个右线的,这样依次迭代

2.求点的坐标,由于每次的夹角是固定的所有每次画V时都用上次的基点和本次的基点求出中点,再将中点和本次基点代入公式,分别求出V的左点和右点的坐标

3.中点坐标的求法,由于每次画的长度是固定的S,所有中点到基点的距离是固定的S*cos(夹角的一半),由于中点,本次基点和上次基点在一条直线上,所以可以求出对应的△x和△y,再对应点在左视图和右视图分别求出坐标即可

4.最后讲一下左点右点的求法,传入基点和中点,基本思路是根据tan的比值先求出中线与竖直线的夹角,再偏转V夹角的一半,根据左线或右线与竖直线的夹角就能求出△x和△y,这样对应的坐标就出来了

package com.lg.drawtree;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

public class LView extends View {
	private double Viewwidge;
	private double Viewhight;
	private Canvas canvas;
	private Paint p;
	private Context context;
	private int X = 15;// 角度
	private int S = 100;// 每次画线的距离
	private Point P = new Point();// 初点
	private int N = 7;//迭代次数

	public LView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context);
	}

	public LView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	public LView(Context context) {
		super(context);
		init(context);
	}

	private void init(Context context) {
		this.context = context;
		p = new Paint();
		p.setStrokeWidth(8);
		p.setAntiAlias(true);// 设置画笔的锯齿效果。 true是去除,大家一看效果就明白了
		p.setColor(Color.GREEN);// 设置绿色
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		Viewwidge = MeasureSpec.getSize(widthMeasureSpec);
		Viewhight = MeasureSpec.getSize(heightMeasureSpec);
		P = new Point(Viewwidge / 2.0, Viewhight*0.75);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		this.canvas = canvas;
		drawTreeL(P, P, N - 1);
	}

	private void drawTreeL(Point p, Point pp, int n) {
		Point pp0 = pp;// 基点新
		Point p1;// 左点
		Point p2;// 右点
		Point p3 = new Point();// 中点
		Point p0 = p;// 基点原
		// 先求中点,
		if (p0.getX() == pp0.getX() && p0.getY() == pp0.getY()) {
			// 先求出初值的中点;
			p3.setX(p0.getX());
			p3.setY(p0.getY() - S * (Math.cos(Math.toRadians(X))));
		} else {
			if (pp0.getX() <= (Viewwidge / 2.0)) {
				// 左侧的中点
				p3.setX(pp0.getX() - (Math.cos(Math.toRadians(X))) * (p0.getX() - pp0.getX()));
				p3.setY(pp0.getY() - (Math.cos(Math.toRadians(X))) * (p0.getY() - pp0.getY()));
			} else {
				// 右侧的中点
				p3.setX((Math.cos(Math.toRadians(X))) * (pp0.getX() - p0.getX()) + pp0.getX());
				p3.setY(pp0.getY() - (Math.cos(Math.toRadians(X))) * (p0.getY() - pp0.getY()));

			}
		}
		if (0 == n) {

		} else {
			p1 = lt(p3, pp0);
			Log.e("LG", "左中点" + p3.toString() + ",左新基点" + p1.toString() + ",原基点" + p0.toString());
			drawT(pp0, p1, this.p);
			drawTreeL(pp0, p1, n - 1);//将新的左点作为下次的基点

			p2 = rt(p3, pp0);
			Log.e("LG", "右中点" + p3.toString() + ",右新基点" + p1.toString() + ",原基点" + p0.toString());
			drawT(pp0, p2, this.p);
			drawTreeL(pp0, p2, n - 1);//将新的右点作为下次的基点
		}
	}

	/** 
	* @Title: lt 
	* @Description: 求左点的坐标
	* @param @param p3 中点
	* @param @param po 本次的基点
	* @param @return    左点 
	* @return Point    返回类型 
	* @throws 
	*/
	private Point lt(Point p3, Point po) {
		double f;
		// 用中点和基点求坐标
		Point pn = new Point();
		if (po.getX() <= (Viewwidge / 2.0)) {
			if ((p3.getY() - po.getY()) == 0) {
				f = Math.toRadians(0) + Math.toRadians(X);
			} else {
				f = Math.atan((po.getX() - p3.getX()) / (po.getY() - p3.getY())) + Math.toRadians(X);
			}
			pn.setX(po.getX() - S * (Math.sin(f)));
			pn.setY(po.getY() - S * (Math.cos(f)));
		} else {
			if ((p3.getY() - po.getY()) == 0) {
				f = Math.toRadians(0) - Math.toRadians(X);
			} else {
				f = Math.atan((p3.getX() - po.getX()) / (po.getY() - p3.getY())) - Math.toRadians(X);
			}
			pn.setX(po.getX() + S * (Math.sin(f)));
			pn.setY(po.getY() - S * (Math.cos(f)));
		}
		return pn;
	}

	/** 
	* @Title: rt 
	* @Description: 求右点的坐标 
	* @param @param p3 中点
	* @param @param po 本次的基点
	* @param @return    右点
	* @return Point    返回类型 
	* @throws 
	*/
	private Point rt(Point p3, Point po) {
		double f;
		// 用中点和基点求坐标
		Point pn = new Point();
		if (po.getX() < (Viewwidge / 2.0)) {
			if ((p3.getY() - po.getY()) == 0) {
				f = Math.toRadians(0) + Math.toRadians(X);
			} else {
				f = Math.atan((po.getX() - p3.getX()) / (po.getY() - p3.getY())) - Math.toRadians(X);
			}
			pn.setX(po.getX() - S * (Math.sin(f)));
			pn.setY(po.getY() - S * (Math.cos(f)));
		} else {
			if ((p3.getY() - po.getY()) == 0) {
				f = Math.toRadians(0) + Math.toRadians(X);
			} else {
				f = Math.atan((p3.getX() - po.getX()) / (po.getY() - p3.getY())) + Math.toRadians(X);
			}
			pn.setX(po.getX() + S * (Math.sin(f)));
			pn.setY(po.getY() - S * (Math.cos(f)));
		}
		return pn;
	}

	private void drawT(Point po, Point pn, Paint p) {
		canvas.drawLine((float) po.getX(), (float) po.getY(), (float) pn.getX(), (float) pn.getY(), p);
	}
}

class Point {
	@Override
	public String toString() {
		return "Point [x=" + x + ", y=" + y + "]";
	}

	/**
	 * @return x
	 */
	public double getX() {
		return x;
	}

	/**
	 * @param x
	 *            要设置的 x
	 */
	public void setX(double x) {
		this.x = x;
	}

	/**
	 * @return y
	 */
	public double getY() {
		return y;
	}

	/**
	 * @param y
	 *            要设置的 y
	 */
	public void setY(double y) {
		this.y = y;
	}

	double x;
	double y;

	Point() {
		this.x = 0;
		this.y = 0;
	}

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

              1,仍存在的问题,当角度超过180度时,对应的角度的三角函数的计算需要改动,(主要是正负的处理)

              2,当迭代次数较大时,画线的长度应随N成递减的趋势

              传一张效果图,欢迎大家提供建议,不足之处望大家提出,谢谢!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值