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;
		}
	}
}


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Linerender组件来绘制曲线,需要通过代码来生成一个曲线上的点集,然后将这些点集赋值给Linerender的position数组。 首先,需要定义一个曲线的方程,比如二次曲线的方程可以表示为y = ax² + bx + c。然后定义曲线上的起始点和终止点,并确定曲线的分段数,对于二次曲线可以横向分成10段。 接着,通过循环计算每个分段的点集,生成所有点的坐标集合,最后将这些点坐标赋值给Linerender的position数组即可。 以下是示例代码实现: ``` using UnityEngine; public class DrawCurve : MonoBehaviour { public LineRenderer lineRenderer; // Linerender组件 public int segmentCount = 10; // 曲线分段数 private Vector3[] points; // 存储曲线上的点坐标集合 private float a = 1, b = 0, c = 0; // 二次曲线方程参数 void Start () { points = new Vector3[segmentCount + 1]; // 初始化数组 // 确定起始点和终止点 Vector3 start = new Vector3(-5, 0, 0); Vector3 end = new Vector3(5, 0, 0); // 循环计算每段的点集 for (int i = 0; i <= segmentCount; i++) { float t = (float)i / segmentCount; // 计算当前位置所处的比例 points[i] = GetPoint(t, start, end); // 根据比例计算点的坐标 } // 将点集赋值给Linerender的position数组 lineRenderer.positionCount = points.Length; lineRenderer.SetPositions(points); } // 计算曲线上的点位置 Vector3 GetPoint(float t, Vector3 start, Vector3 end) { Vector3 p = Vector3.Lerp(start, end, t); // 根据当前位置比例计算点在线段上的位置 p.y = a * p.x * p.x + b * p.x + c; // 根据二次曲线方程计算y坐标 return p; } } ``` 在Linerender组件上调整线宽、材质等属性,即可看到绘制出的曲线

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值