unity 绘制Bezier曲线

绘制Bezier曲线


using UnityEngine;
using System.Collections.Generic;
using System;


namespace MyTools{
	[System.Serializable]

	/// <summary>
	/// 贝塞尔曲线
	/// </summary>
	public class Bezier :System.Object {
		private List <Vector3> m_Points;
		private List <Line> createdLine;
		/// <summary>
		/// Initializes a new instance of the <see cref="MyTools.Bezier"/> class.
		/// </summary>
		/// <param name="points">Points.</param>
		public Bezier(List<Vector3> points){
			if (points.Count < 2) {
				throw(new ArgumentException ("实例化贝塞尔曲线至少需要2个点"));
			} else {
				m_Points = new List<Vector3> ();
				createdLine = new List<Line> ();
				CreateLine (points);
			}
		}
		#region 修改参数的方法
		public void AddPoint(Vector3 point){
			m_Points.Add (point);
			CreateLine (m_Points);
		}

		public void AddPointAt(int index,Vector3 point){
			m_Points.Add (point);
			var buf = m_Points [index];
			m_Points [index] = point;
			m_Points [m_Points.Count - 1] = buf;
			CreateLine (m_Points);
		}

		public void RemovePoint(Vector3 point){
			if (m_Points.Count > 2) {
				for (int i = 0; i < m_Points.Count; i++) {
					if (m_Points [i] == point) {
						m_Points.RemoveAt (i);
						CreateLine (m_Points);
					} else {
						continue;
					}
				}
			} else {
				Exception ex = new Exception ("当前曲线锚点数量已经最低,不能移除锚点");
				throw(ex);
			}
		}

		public void RemovePointAt(int index){
			if (m_Points.Count > 2) {
				m_Points.RemoveAt (index);
				CreateLine (m_Points);
			} else {
				Exception ex = new Exception ("当前曲线锚点数量已经最低,不能移除锚点");
				throw(ex);
			}
		}

		public void UpdatePoint(int ListIndex, Vector3 point){
			if (ListIndex < 0) {
				throw (new ArgumentException ("坐标索引参数错误(取值必须大于0)"));
			} else if (ListIndex >= m_Points.Count) {
				throw (new ArgumentException ("坐标索引参数错误(取值必须x小于曲线顶点的个数)"));
			} else {
				m_Points [ListIndex] = point;
				CreateLine (m_Points);
			}
		}

		#endregion

		/// <summary>
		/// 根据传入的参数获取曲线上某一点的值
		/// </summary>
		/// <returns>The point.</returns>
		/// <param name="T">取值参数(0-1).</param>
		public Vector3 GetPoint(float T){
			var point = new Vector3 ();
			if (T < 0) {
				T = 0;
			} else if (T > 1) {
				
				T = 1;
			}
			var bufListLine = createdLine;
			if (bufListLine == null) {
				throw(new NullReferenceException ("曲线锚点为空"));
			}
			while (bufListLine.Count > 1) {
		
				bufListLine = CaculateResoultLine (bufListLine, T);
			}
			if (bufListLine.Count == 1) {
				point = bufListLine [0].GetPoint (T);
			} else {
				throw(new Exception("Program Error : Current Line Count is:   " + bufListLine.Count));
			}

			return point;

		}
		/// <summary>
		/// 根据当前的线段以及取值参数T,创建新的线段链表(新的链表长度始终等于原始链表长度-1)。
		/// 使用迭代计算的方式降低程序的复杂性
		/// </summary>
		/// <param name="Lines">Lines.</param>
		/// <param name="T">T.</param>
		private List<Line> CaculateResoultLine(List<Line> Lines,float T){
			var ListLine = new List<Line>();
			for (int i = 0; i < Lines.Count-1; i++) {
				var j = i + 1;
				Line bufLine = new Line (Lines [i].GetPoint (T),Lines [j].GetPoint (T));
				ListLine.Add (bufLine);
			}
			return ListLine;
		}
		/// <summary>
		/// 根据已知的锚点依次创建一条连续的折线
		/// </summary>
		/// <param name="points">Points.</param>
		private void CreateLine(List<Vector3> points){
			createdLine = new List<Line> ();
			m_Points = points;
			for (int i = 0; i < points.Count; i++) {
				var j = i + 1;
				if (j >= points.Count) {
					break;
				} else {
					Line curLine = new Line (points [i], points [j]);
					createdLine.Add (curLine);
				}
			}
		}
	}
	/// <summary>
	/// 线段,包含起点和终点
	/// </summary>
	public struct Line{
		public Line(Vector3 start,Vector3 end){
			StartPoint = start;
			EndPoint = end;
		}
		/// <summary>
		/// 线段的起点
		/// </summary>
		/// <value>The start point.</value>
		public Vector3 StartPoint {
			get;
			set;
		}
		/// <summary>
		/// 线段的终点
		/// </summary>
		/// <value>The end point.</value>
		public Vector3 EndPoint{
			get;
			set;
		}
		/// <summary>
		/// 判断一个点是否是自己的起点或者终点
		/// </summary>
		/// <returns><c>true</c>, if me was ised, <c>false</c> otherwise.</returns>
		/// <param name="point">Point.</param>
		public bool isMe(Vector3 point){
			if (StartPoint == point || EndPoint == point) {
				return true;
			} else {
				return false;
			}
		}
		/// <summary>
		/// 根据传入的值获取这条线段上的任意一点,T>=0&&T<=1
		/// T=0时返回起点
		/// T=1时返回终点
		/// </summary>
		/// <returns>The point.</returns>
		/// <param name="T">T.</param>
		public Vector3 GetPoint(float T){
			var point = new Vector3 ();
			if (T < 0) {
				T = 0;
			} else if (T > 1) {
				T = 1;
			}
			point = (EndPoint - StartPoint) * T + StartPoint;
			return point;
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值