Unity 实用方法 合集

Unity 实用方法 合集

  • Unity 打字机效果
  • 2D 坐标旋转计算
  • 球面坐标求值
  • 平滑移动
  • 鼠标位置获取2D
  • 屏幕坐标转世界坐标
  • 物体朝向目标
  • 多物体中心点生成
  • 本地图片加载
  • 画面线框显示
    • 画面线框显示 搭载效果
  • 贝塞尔曲线绘制
    • 贝塞尔曲线绘制 搭载效果
  • 网格弯曲
    • 网格弯曲 搭载效果
  • Delaunay 模型生成

代码很简单没有难度,都有注解,可以收藏一下方便后期使用。

Unity 打字机效果

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;/// <summary>
/// 打字机效果
/// </summary>
public class TextWriter_ZH : MonoBehaviour
{[Header("打字速度")]public float _Delay = 0.1f;[Header("完整的文字")]public string _FullText;// 当前显示的文字private string _CurrentText = "";// 计时器private float _Timer;// 当前字符索引private int _CurrentIndex = 0; void Start(){StartCoroutine(ShowText());}void Update(){if (Input.GetKeyDown(KeyCode.T)){// 获取当前时间,精确到秒级float _CurrentTime = Time.time;// 将秒级时间转换为毫秒级时间int _Milliseconds = (int)((_CurrentTime - Mathf.Floor(_CurrentTime)) * 1000); Debug.Log("Current Time: " + System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss." + _Milliseconds.ToString("000")));_FullText = "当前时间是: " + System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss." + _Milliseconds.ToString("000"));//初始化GetComponent<Text>().text = "";_CurrentIndex = 0;}}/// <summary>/// 文字显示/// </summary>/// <returns></returns>IEnumerator ShowText(){//字符长度判断while (_CurrentIndex < _FullText.Length){//时间累加_Timer += Time.deltaTime;if (_Timer >= _Delay){//文字输出_CurrentText += _FullText[_CurrentIndex];//显示GetComponent<Text>().text = _CurrentText;//步进_CurrentIndex++;_Timer = 0;}yield return null;}}
}

2D 坐标旋转计算

原理:以自身为原点,计算增加半径 R 并且旋转 指定角度后 圆上坐标
应用:应用方向有很多吧 比如旋转动量计算,等边三角形遍历等
  /// <summary>/// 2D 坐标旋转计算/// </summary>public void AngleCalculation2D(){// 假设原坐标的 x 值为 3double _X = 3;// 假设原坐标的 y 值为 4double _Y = 4;// 假设半径为 5double _Radius = 5;// 假设旋转角度为 30 度double _Angle = 30;// 将角度转换为弧度double _Radian = _Angle * Math.PI / 180;// 计算旋转后的 X Y 坐标double _NewX = _X * Math.Cos(_Radian) - _Y * Math.Sin(_Radian);double _NewY = _X * Math.Sin(_Radian) + _Y * Math.Cos(_Radian);// 计算旋转后点的距离原点的半径double _NewRadius = Math.Sqrt(_NewX * _NewX + _NewY * _NewY);// 考虑半径对坐标的缩放double _FinalX = _NewX * _Radius / _NewRadius;double _FinalY = _NewY * _Radius / _NewRadius;Vector2 _Vector2 = new Vector2((float)_FinalX, (float)_FinalY);Console.WriteLine("旋转后的坐标:({0})", _Vector2);}

球面坐标求值

原理:根据给定的圆心坐标和目标坐标,得到圆心到目标位置的向量。根据要求的延长半径和旋转角度再把夹角转换为弧度之后得到目标点的球面坐标值 并返回
应用:球面计算和均匀分配
 /// <summary>/// 3D 坐标旋转计算/// </summary>/// <param 圆心坐标="_Center"></param>/// <param 半径="_Radius"></param>/// <param 目标位置="_PointA"></param>/// <param 旋转角度="_Angle"></param>public void AngleCalculation3D(Vector3 _Center, float _Radius, Vector3 _PointA, float _Angle){ 假设圆心坐标为 (1, 2, 3)//Vector3 _Center = new Vector3(1, 2, 3); 假设半径为 5//float _Radius = 5; 假设三维坐标点 a 为 (4, 5, 6)//Vector3 _PointA = new Vector3(4, 5, 6); 假设旋转角度为 30 度//float _Angle = 30;//转换后球面坐标值Vector3 _RotatedPoint = RotatePoint(_Center, _PointA, _Radius, _Angle);Console.WriteLine("旋转后的球面坐标:");//magnitude 返回该向量的长度Console.WriteLine("半径:{0}", _RotatedPoint.magnitude);//Rad2Deg 弧度到度数的转换常数Console.WriteLine("纬度:{0}", Mathf.Rad2Deg * Mathf.Asin(_RotatedPoint.normalized.y));Console.WriteLine("经度:{0}", Mathf.Rad2Deg * Mathf.Atan2(_RotatedPoint.normalized.z, _RotatedPoint.normalized.x));}
    /// <summary>/// 球面坐标求值/// </summary>/// <param 圆心坐标="_Center"></param>/// <param 目标位置="_Point"></param>/// <param 半径="_Radius"></param>/// <param 旋转角度="_Angle"></param>/// <returns></returns>public static Vector3 RotatePoint(Vector3 _Center, Vector3 _Point, float _Radius, float _Angle){// 统一坐标系Vector3 _ShiftedPoint = _Point - _Center;// 计算旋转后的坐标float _Radian = _Angle * Mathf.Deg2Rad;float _RotatedX = _ShiftedPoint.x * Mathf.Cos(_Radian) - _ShiftedPoint.z * Mathf.Sin(_Radian);float _RotatedY = _ShiftedPoint.y;float _RotatedZ = _ShiftedPoint.x * Mathf.Sin(_Radian) + _ShiftedPoint.z * Mathf.Cos(_Radian);// 计算旋转后的球面坐标Vector3 _RotatedPoint = new Vector3(_RotatedX, _RotatedY, _RotatedZ).normalized * _Radius;// 返回旋转后的点return _RotatedPoint;}

平滑移动

原理:Vector3.Lerp 插值计算  然后返回趋近值
应用:字面意思  平滑 可以应用到双曲线螺旋
  /// <summary>/// 平滑移动/// </summary>/// <param name="_ObjectToMove"></param>/// <param name="_TargetPosition"></param>/// <param name="_Duration"></param>/// <returns></returns>public IEnumerator SmoothMoveObject(Transform _ObjectToMove, Vector3 _TargetPosition, float _Duration){float _ElapsedTime = 0f;Vector3 _StartingPosition = _ObjectToMove.position;while (_ElapsedTime < _Duration){_ObjectToMove.position = Vector3.Lerp(_StartingPosition, _TargetPosition, _ElapsedTime / _Duration);_ElapsedTime += Time.deltaTime;yield return null;}_ObjectToMove.position = _TargetPosition;}

鼠标位置获取2D

原理:Camera.main.ScreenToWorldPoint
应用:获取鼠标在2D空间中的位置,通常用于2D游戏的鼠标交互
   /// <summary>/// 鼠标位置获取/// </summary>/// <returns></returns>public Vector2 GetMousePosition2D(){Vector3 _MousePosition = Input.mousePosition;_MousePosition.z = -Camera.main.transform.position.z;return Camera.main.ScreenToWorldPoint(_MousePosition);}

屏幕坐标转世界坐标

原理:Camera.main.ScreenToWorldPoint
应用:将屏幕坐标转换为世界坐标,通常用于将鼠标点击位置转换为游戏世界中的坐标
    /// <summary>/// 屏幕坐标转世界坐标/// </summary>/// <param name="screenPosition"></param>/// <returns></returns>public Vector3 ScreenToWorldPoint(Vector3 _ScreenPosition){return Camera.main.ScreenToWorldPoint(_ScreenPosition);}

物体朝向目标

原理: Quaternion.LookRotation()
应用:使物体的正面朝向目标位置
   /// <summary>/// 物体朝向目标/// </summary>/// <param 当前物体 ="_ObjectToRotate"></param>/// <param 朝向目标 ="_TargetPosition"></param>public void LookAtTarget(Transform _ObjectToRotate, Vector3 _TargetPosition){Vector3 _Direction = _TargetPosition - _ObjectToRotate.position;Quaternion _Rotation = Quaternion.LookRotation(_Direction);_ObjectToRotate.rotation = _Rotation;}

多物体中心点生成

原理:所有位置向量累加并除以数量得到平均值
应用:鱼群算法中心计算、多物体连线等
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 多物体中心点判定
/// </summary>
public class ObjectsCenterPoint_ZH : MonoBehaviour
{public List<GameObject> _GameObject; // 存储多个物体的数组private void Start(){// 计算中心点Vector3 _CenterPoint = CalculateCenterPoint();// 在场景中创建一个表示中心点的标记物体CreateCenterPointMarker(_CenterPoint);}/// <summary>/// 中心点坐标/// </summary>/// <returns></returns>Vector3 CalculateCenterPoint(){Vector3 _CenterPoint = Vector3.zero;// 累加所有物体的位置foreach (GameObject obj in _GameObject){_CenterPoint += obj.transform.position;}// 求取平均位置_CenterPoint /= _GameObject.Count;return _CenterPoint;}/// <summary>/// 中心点位置 物体生成/// </summary>/// <param 中心点位置="_CenterPoint"></param>void CreateCenterPointMarker(Vector3 _CenterPoint){// 在场景中创建一个标记物体表示中心点GameObject _Marker = GameObject.CreatePrimitive(PrimitiveType.Sphere);_Marker.transform.position = _CenterPoint;_Marker.transform.localScale = Vector3.one * 0.5f;_Marker.GetComponent<Renderer>().material.color = Color.red;}
}

本地图片加载

原理:IO流 读取
应用:场景加载界面或则动态变更图标
using UnityEngine;
using UnityEngine.UI;/// <summary>
/// 图片加载
/// </summary>
public class ImageLoader_ZH : MonoBehaviour
{public string _ImagePath;public RawImage _RawImage;private void Start(){// 加载本地图片Texture2D _Texture = LoadLocalImage(_ImagePath);if (_Texture != null){// 将纹理设置给RawImage组件进行显示_RawImage.texture = _Texture;}else{Debug.LogError("没有显示载体。");}}private Texture2D LoadLocalImage(string _Path){// 使用Unity的API加载本地图片// 创建一个空的Texture2D对象Texture2D _Texture = new Texture2D(2, 2);// 读取图片数据byte[] _ImageData = System.IO.File.ReadAllBytes(_Path);// 将图片数据加载到Texture2D对象中bool _Success = _Texture.LoadImage(_ImageData); if (_Success){return _Texture;}else{Destroy(_Texture); // 加载失败时销毁Texture2D对象return null;}}
}

画面线框显示

原理: 就是 GL 绘画应用变形
应用:画面标注、主题框选等
	/// <summary>/// 在渲染后执行/// 屏幕框选/// </summary>private void OnPostRender(){//画线这种操作推荐在 OnPostRender()里进行 而不是直接放在Update,所以需要标志来开启if (_IsSelecting){//开始绘图位置var startMousePosition = MousePosition;//鼠标当前位置Vector3 _MouseEnd = Input.mousePosition;//保存摄像机变换矩阵GL.PushMatrix();//显示材质if (!_RectMat){return;} else{//生成画线的材质_RectMat = new Material(Shader.Find("UI/Default"));//GameObject(游戏对象)没有显示在层次结构中,没有保存到场景中,也没有被Resources.UnloadUnusedAssets卸载。_RectMat.hideFlags = HideFlags.HideAndDontSave;//Gameobject(游戏对象)没有显示在层次结构中,没有保存到场景中,也没有被Resources.UnloadUnusedAssets卸载_RectMat.shader.hideFlags = HideFlags.HideAndDontSave;}_RectMat.SetPass(0);//设置用屏幕坐标绘图GL.LoadPixelMatrix();GL.Begin(GL.QUADS);//设置颜色和透明度,方框内部透明GL.Color(new Color(_RectColor.r, _RectColor.g, _RectColor.b, 0.1f));GL.Vertex3(startMousePosition.x, startMousePosition.y, 0);GL.Vertex3(_MouseEnd.x, startMousePosition.y, 0);GL.Vertex3(_MouseEnd.x, _MouseEnd.y, 0);GL.Vertex3(startMousePosition.x, _MouseEnd.y, 0);GL.End();GL.Begin(GL.LINES);//设置方框的边框颜色 边框不透明GL.Color(_RectColor);GL.Vertex3(startMousePosition.x, startMousePosition.y, 0);GL.Vertex3(_MouseEnd.x, startMousePosition.y, 0);GL.Vertex3(_MouseEnd.x, startMousePosition.y, 0);GL.Vertex3(_MouseEnd.x, _MouseEnd.y, 0);GL.Vertex3(_MouseEnd.x, _MouseEnd.y, 0);GL.Vertex3(startMousePosition.x, _MouseEnd.y, 0);GL.Vertex3(startMousePosition.x, _MouseEnd.y, 0);GL.Vertex3(startMousePosition.x, startMousePosition.y, 0);GL.End();//恢复摄像机投影矩阵GL.PopMatrix();}}

画面线框显示 搭载效果

请添加图片描述

贝塞尔曲线绘制

原理:P(t) = (1 - t)^2 * P0 + 2 * (1 - t) * t * P1 + t^2 * P2曲线上的点可以通过参数t(取值范围为01)来表示。参数t表示曲线上某一点的位置,其中t=0表示起点,t=1表示终点。对于给定的t值,可以使用以下公式计算曲线上的点P(t)的坐标:其中,P0P1P2分别是起点、控制点和终点的坐标。
应用:物体弯曲,道路生成,画面扭曲等扩展:三次贝塞尔曲线:三次贝塞尔曲线由四个锚点(起点、终点和两个控制点)组成。P(t) = (1 - t)^3 * P0 + 3 * (1 - t)^2 * t * P1 + 3 * (1 - t) * t^2 * P2 + t^3 * P3P0P1P2P3分别是起点、两个控制点和终点的坐标。通过调整控制点的位置,可以改变贝塞尔曲线的形状。控制点的位置决定了曲线的弯曲程度和方向。
using UnityEngine;
/// <summary>
/// 贝塞尔曲线绘制
/// </summary>
public class BezierCurve_ZH : MonoBehaviour
{[Header("开始位置")]public Transform _StartPoint;[Header("控制带你")]public Transform _ControlPoint;[Header("结束位置")]public Transform _EndPoint;[Header("精度")]//越高越平滑  性能消耗越大public int _Resolution = 10;private void OnDrawGizmos(){DrawBezierCurve();}/// <summary>/// 贝塞尔曲线绘制/// </summary>private void DrawBezierCurve(){//曲线数组Vector3[] _Points = new Vector3[_Resolution + 1];//数组变更for (int i = 0; i <= _Resolution; i++){float t = i / (float)_Resolution;_Points[i] = CalculatePointOnCurve(t);}//绘制颜色Gizmos.color = Color.cyan;//曲线绘制for (int i = 0; i < _Resolution; i++){Gizmos.DrawLine(_Points[i], _Points[i + 1]);}}/// <summary>/// 计算曲线上的点/// </summary>/// <param name="t"></param>/// <returns></returns>private Vector3 CalculatePointOnCurve(float t){float u = 1 - t;float tt = t * t;float uu = u * u;Vector3 point = uu * _StartPoint.position;point += 2 * u * t * _ControlPoint.position;point += tt * _EndPoint.position;return point;}
}

贝塞尔曲线绘制 搭载效果

请添加图片描述

网格弯曲

原理:使用 三次贝塞尔曲线 得到变形后的顶点,然后根据变形后的顶点进行网格重组	 
应用:物体弯曲,道路生成,画面扭曲等
using UnityEngine;/// <summary>
/// 网格弯曲
/// </summary>
public class ObjectBender_ZH : MonoBehaviour
{//起始点public Transform _StartPoint;//控制点 1public Transform _ControlPoint1;//控制点 2public Transform _ControlPoint2;//结束点public Transform _EndPoint;//精细程度public int _Eesolution = 10;//变形网格public MeshFilter _MeshFilter;//出十万个private Mesh _OriginalMesh;//变形网格private Mesh _BentMesh;private void Start(){//初始化//_MeshFilter = GetComponent<MeshFilter>();_OriginalMesh = _MeshFilter.mesh;_BentMesh = new Mesh();_MeshFilter.mesh = _BentMesh;BendObject();}private void Update(){BendObject();}/// <summary>/// 网格变形方法/// </summary>private void BendObject(){//顶点数组Vector3[] _Vertices = _OriginalMesh.vertices;//变形顶点数组Vector3[] _BentVertices = new Vector3[_Vertices.Length];//变形顶点 遍历赋值for (int i = 0; i < _Vertices.Length; i++){Vector3 vertex = _Vertices[i];Vector3 bentPosition = BendVertex(vertex);_BentVertices[i] = bentPosition;}//顶点  三角面  法线 设置_BentMesh.vertices = _BentVertices;_BentMesh.triangles = _OriginalMesh.triangles;_BentMesh.RecalculateNormals();}/// <summary>/// 顶点变形 重组/// </summary>/// <param name="_Vertex"></param>/// <returns></returns>private Vector3 BendVertex(Vector3 _Vertex){float t = _Vertex.x / (float)(_OriginalMesh.bounds.size.x);Vector3 _StartPointPosition = _StartPoint.position;Vector3 _ControlPoint1Position = _ControlPoint1.position;Vector3 _ControlPoint2Position = _ControlPoint2.position;Vector3 _EndPointPosition = _EndPoint.position;Vector3 _BentPosition = CalculatePointOnCurve(t, _StartPointPosition, _ControlPoint1Position, _ControlPoint2Position, _EndPointPosition);return _BentPosition;}/// <summary>/// 曲线计算/// 三次贝塞尔曲线/// </summary>/// <param 变形 t ="t"></param>/// <param 开始位置="_StartPoint"></param>/// <param 控制点01="_ControlPoint1"></param>/// <param 控制点02 ="_ControlPoint2"></param>/// <param 结束位置="_EndPoint"></param>/// <returns></returns>private Vector3 CalculatePointOnCurve(float t, Vector3 _StartPoint, Vector3 _ControlPoint1, Vector3 _ControlPoint2, Vector3 _EndPoint){float t2 = t * t;float t3 = t2 * t;Vector3 _Point =0.5f * ((2.0f * _ControlPoint1) +(-_StartPoint + _EndPoint) * t +(2.0f * _StartPoint - 5.0f * _ControlPoint1 + 4.0f * _ControlPoint2 - _EndPoint) * t2 +(-_StartPoint + 3.0f * _ControlPoint1 - 3.0f * _ControlPoint2 + _EndPoint) * t3);return _Point;}
}

网格弯曲 搭载效果

注意需要勾选导入模型的读写权限

请添加图片描述

变形前

请添加图片描述

变形后

请添加图片描述

Delaunay 模型生成

原理:就是使用 Delaunay 算法进行 外接圆判断
应用:模型生成、动态模型补面、最大面积计算等
有一点不完善,过两天抽时间单独研究研究,再出一篇看看。

填坑了哈,大家如果有兴趣可以去看看。
Delaunay 算法 的 解析 : Unity Delaunay三角剖分算法

using UnityEngine;
using System.Collections.Generic;/// <summary>
///  Delaunay 模型生成
/// </summary>
public class DelaunayAlgorithm : MonoBehaviour
{[Header("存储要生成 Delaunay 物体")]public List<Transform> _TraList = new List<Transform>();[Header("存储要生成 Delaunay 三角网格的点")]private List<Vector2> _Points = new List<Vector2>();// 存储生成的三角形private List<Triangle> _Triangles = new List<Triangle>(); private void Start(){for (int i = 0; i < _TraList.Count; i++){_Points.Add(new Vector2(_TraList[i].position.x, _TraList[i].position.z));}GenerateDelaunay();}/// <summary>/// Delaunay 三角形生成/// </summary>void GenerateDelaunay(){// 在点集中加入一个超级三角形float _MinX = float.MaxValue;float _MinY = float.MaxValue;float _MaxX = float.MinValue;float _MaxY = float.MinValue;//最大值最小值判定foreach (Vector2 _Point in _Points){if (_Point.x < _MinX) _MinX = _Point.x;if (_Point.y < _MinY) _MinY = _Point.y;if (_Point.x > _MaxX) _MaxX = _Point.x;if (_Point.y > _MaxY) _MaxY = _Point.y;}float _DeltaX = _MaxX - _MinX;float _DeltaY = _MaxY - _MinY;float _DeltaMax = Mathf.Max(_DeltaX, _DeltaY);float _MidX = (_MinX + _MaxX) / 2f;float _MidY = (_MinY + _MaxY) / 2f;Vector2 p1 = new Vector2(_MidX - 20 * _DeltaMax, _MidY - _DeltaMax);Vector2 p2 = new Vector2(_MidX, _MidY + 20 * _DeltaMax);Vector2 p3 = new Vector2(_MidX + 20 * _DeltaMax, _MidY - _DeltaMax);//三角形片元 添加_Triangles.Add(new Triangle(p1, p2, p3));// 逐个加入点并更新三角形foreach (Vector2 _Point in _Points){List<Edge> _Polygon = new List<Edge>();for (int i = _Triangles.Count - 1; i >= 0; i--){//如果是外接圆就证明 当前三角形是 Delaunay 三角形//如果有任何一个点在其他三角形的外接圆内,则该三角形不是Delaunay三角形。if (_Triangles[i].CircumcircleContains(_Point)){_Polygon.Add(_Triangles[i].e1);_Polygon.Add(_Triangles[i].e2);_Polygon.Add(_Triangles[i].e3);_Triangles.RemoveAt(i);}}//顶点移除for (int i = _Polygon.Count - 2; i >= 0; i--){for (int j = _Polygon.Count - 1; j >= i + 1; j--){if (_Polygon[i] == _Polygon[j]){_Polygon.RemoveAt(j);_Polygon.RemoveAt(i);j--;}}}//加入片元 数组foreach (Edge edge in _Polygon){_Triangles.Add(new Triangle(edge.p1, edge.p2, _Point));}}// 剔除超级三角形相关的三角形List<Triangle> _TrianglesToRemove = new List<Triangle>();foreach (Triangle _Triangle in _Triangles){if (_Triangle.ContainsAnyVertex(p1, p2, p3)){_TrianglesToRemove.Add(_Triangle);}}foreach (Triangle triangle in _TrianglesToRemove){_Triangles.Remove(triangle);}// 在 Unity 中绘制生成的三角形  Delaunayforeach (Triangle _Triangle in _Triangles){//if (_Triangle.e1.IsDelaunayEdge(_Triangles))//{//    Debug.DrawLine(_Triangle.p1, _Triangle.p2, Color.green, 15f);//}//if (_Triangle.e2.IsDelaunayEdge(_Triangles))//{//    Debug.DrawLine(_Triangle.p2, _Triangle.p3, Color.green, 15f);//}//if (_Triangle.e3.IsDelaunayEdge(_Triangles))//{//    Debug.DrawLine(_Triangle.p3, _Triangle.p1, Color.green, 15f);//}Debug.DrawLine(_Triangle.p1, _Triangle.p2, Color.green, 15f);Debug.DrawLine(_Triangle.p2, _Triangle.p3, Color.green, 15f);Debug.DrawLine(_Triangle.p3, _Triangle.p1, Color.green, 15f);}}
}/// <summary>
/// 三角形数据类
/// </summary>
public class Triangle
{// 三角形的顶点public Vector2 p1, p2, p3;// 三角形的边public Edge e1, e2, e3;/// <summary>/// 三角形  片元/// </summary>/// <param 顶点="p1"></param>/// <param 顶点="p2"></param>/// <param 顶点="p3"></param>/// <returns></returns>public Triangle(Vector2 p1, Vector2 p2, Vector2 p3){this.p1 = p1;this.p2 = p2;this.p3 = p3;e1 = new Edge(p1, p2);e2 = new Edge(p2, p3);e3 = new Edge(p3, p1);}/// <summary>/// 检查三角形的外接圆是否包含指定的点/// 给定的点在三角形的外接圆内,返回true;否则,说明给定的点不在外接圆内,返回false/// </summary>/// <param 顶点="point"></param>/// <returns></returns>public bool CircumcircleContains(Vector2 point){//计算三角形的外接圆的圆心和半径float d1 = (p1.x - point.x) * (p1.x - point.x) + (p1.y - point.y) * (p1.y - point.y);float d2 = (p2.x - point.x) * (p2.x - point.x) + (p2.y - point.y) * (p2.y - point.y);float d3 = (p3.x - point.x) * (p3.x - point.x) + (p3.y - point.y) * (p3.y - point.y);float a = (p1.x * (p2.y - p3.y) + p2.x * (p3.y - p1.y) + p3.x * (p1.y - p2.y)) * 2f;if (Mathf.Abs(a) < 0.00001f){return false;}//检查指定点与圆心的距离是否小于或等于半径的平方float centerX = ((p1.x * p1.x + p1.y * p1.y) * (p2.y - p3.y) + (p2.x * p2.x + p2.y * p2.y) * (p3.y - p1.y) + (p3.x * p3.x + p3.y * p3.y) * (p1.y - p2.y)) / a;float centerY = ((p1.x * p1.x + p1.y * p1.y) * (p3.x - p2.x) + (p2.x * p2.x + p2.y * p2.y) * (p1.x - p3.x) + (p3.x * p3.x + p3.y * p3.y) * (p2.x - p1.x)) / a;float radius = Mathf.Sqrt((centerX - p1.x) * (centerX - p1.x) + (centerY - p1.y) * (centerY - p1.y));float dist = (point.x - centerX) * (point.x - centerX) + (point.y - centerY) * (point.y - centerY);return dist <= radius * radius;}/// <summary>/// 检查三角形是否包含指定的顶点/// 最大三角形判定/// </summary>/// <param name="v1"></param>/// <param name="v2"></param>/// <param name="v3"></param>/// <returns></returns>public bool ContainsAnyVertex(Vector2 v1, Vector2 v2, Vector2 v3){return p1 == v1 || p1 == v2 || p1 == v3 ||p2 == v1 || p2 == v2 || p2 == v3 ||p3 == v1 || p3 == v2 || p3 == v3;}/ <summary>/ Delaunay边  判定/ 确定是否绘制当前三角形的边/ </summary>/ <returns></returns>//public bool IsDelaunay()//{//    // 检查三角形的每条边是否是Delaunay边//    //return e1.IsDelaunayEdge() && e2.IsDelaunayEdge() && e3.IsDelaunayEdge();//}}/// <summary>
/// 三角边
///  表示边的类
/// </summary>
public class Edge
{// 边的两个顶点public Vector2 p1, p2;public Edge(Vector2 p1, Vector2 p2){this.p1 = p1;this.p2 = p2;}/// <summary>///  重写 Equals 方法,用于比较边的相等性/// </summary>/// <param name="obj"></param>/// <returns></returns>public override bool Equals(object obj){if (obj == null || GetType() != obj.GetType()){return false;}Edge other = (Edge)obj;return (p1 == other.p1 && p2 == other.p2) || (p1 == other.p2 && p2 == other.p1);}/// <summary>///  重写 GetHashCode 方法,用于哈希表存储/// </summary>/// <returns></returns>public override int GetHashCode(){return p1.GetHashCode() ^ p2.GetHashCode();}/// <summary>///  Delaunay 三角边判断/// </summary>/// <param 三角片元数组="_Triangles"></param>/// <returns></returns>public bool IsDelaunayEdge(List<Triangle> _Triangles){// 检查当前边是否与其他三角形的外接圆相交foreach (Triangle _Triangle in _Triangles){if (_Triangle.CircumcircleContains(new Vector2(p1.x, p1.y)) || _Triangle.CircumcircleContains(new Vector2(p2.x, p2.y))){return false;}}return true;}
}
最大三角形

请添加图片描述

生成物体分布

请添加图片描述

生成网格 有点问题 需要后期修改

请添加图片描述

暂时先这样吧,如果有时间的话就会更新,实在看不明白就留言,看到我会回复的。
路漫漫其修远兮,与君共勉。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/611106.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安泰ATA-4014高压功率放大器在传感器脉冲涡流检测中的应用

传感器在工程领域起着至关重要的作用&#xff0c;能够实时获取各种物理量的信息。而功率放大器作为传感器信号处理的重要组成部分&#xff0c;广泛应用于各种测量和控制系统中。本文将探讨功率放大器在这一领域的重要性和作用。 首先&#xff0c;了解传感器脉冲涡流检测的基本原…

二、电脑备份

一、电脑备份 解释&#xff1a;window10目前有电脑备份的功能&#xff0c;一般备份C盘(因为系统在这里)&#xff0c;这个功能挺重要的&#xff0c;能够帮你在危难的时候把电脑拉回来&#xff0c;在按照xxxx教程安装驱动&#xff0c;操作注册表&#xff0c;修改C盘里面跟系统有…

亚信安慧AntDB团队引领数据库创新浪潮

湖南亚信安慧科技有限公司&#xff0c;原亚信科技AntDB团队&#xff0c;近日获得信创工委会颁发的创新活跃度荣誉&#xff0c;充分肯定了其在科技创新领域的杰出表现。在当前全球经济下行的大环境中&#xff0c;创新正逐渐成为国家、企业和个人发展的关键因素。亚信安慧作为一家…

AI芯片:神经网络研发加速器、神经网络压缩简化、通用芯片 CPU 加速、专用芯片 GPU 加速

AI芯片&#xff1a; 神经网络研发加速器、神经网络压缩简化、通用芯片 CPU 加速、专用芯片 GPU 加速 神经网络研发加速器神经网络编译器神经网络编译器 神经网络加速与压缩&#xff08;算法层面&#xff09;知识蒸馏低秩分解轻量化网络剪枝量化 通用芯片 CPU 加速x86 加速arm 加…

【Linux】应用与驱动交互及应用间数据交换

一、应用程序与 Linux 驱动交互主要通过以下几种方式&#xff1a; 1. 系统调用接口&#xff08;System Calls&#xff09;: 应用程序可以通过系统调用&#xff0c;如 open(), read(), write(), ioctl(), 等来与设备驱动进行交互。这些调用最终会通过内核转发到相应的驱动函数…

安装ubuntu22.04系统,GPU驱动,cuda,cudnn,python环境,pycharm

需要准备一个u盘&#xff0c;需要格式化&#xff0c;且内存不小于8g 1 下载ubuntu镜像 下载链接&#xff1a; https://cn.ubuntu.com/download/desktop 2下载rufus Rufus - 轻松创建 USB 启动盘Rufus: Create bootable USB drives the easy wayhttps://rufus.ie/zh/ 准备好这…

Abp 创建一个模版demo并运行

Demo效果 &#xff1a;简单的单表crud后台服务。不包含UI 项目类型是模块ABP。生成的结构和 多应用/单应用 有差异。 结合文档以及git的源码分享一下demo的理解 abp文档&#xff1a;API/Auto API Controllers | Documentation Center | ABP.IO 前置准备&#xff1a; Net8 环境…

鹅目标检测数据集VOC格式300张

鹅&#xff0c;一种家禽&#xff0c;以其独特的形态、生活习性和文化象征意义而备受人们喜爱。 鹅属于鸟纲、雁形目、鸭科&#xff0c;是一种大型水禽。它们的身体肥胖&#xff0c;羽毛洁白如雪&#xff0c;嘴部扁平且坚硬&#xff0c;脚部有蹼&#xff0c;适合在水中游动。 …

VBA_NZ系列工具NZ11:VBA光标跟随策略

我的教程一共九套及VBA汉英手册一部&#xff0c;分为初级、中级、高级三大部分。是对VBA的系统讲解&#xff0c;从简单的入门&#xff0c;到数据库&#xff0c;到字典&#xff0c;到高级的网抓及类的应用。大家在学习的过程中可能会存在困惑&#xff0c;这么多知识点该如何组织…

【vue3中状态管理工具pinia的使用】pinia状态一(state)

1、安装 yarn add pinia//或者//npm install pinia2、在main.js中引入store // 引入piniaimport { createPinia } from piniaconst pinia createPinia()// 使用piniaapp.use(pinia)3、创建一个Store 在项目根目录的 src文件夹 —— 创建store文件夹 —— 创建 index.js 文件 …

MongoDB查找命令find,让数据返回称心如意

业务系统接入数据库后&#xff0c;每天都有大量的数据写入数据库。面对逐日增加的数据&#xff0c;开发人员或数据分析人员&#xff0c;该如何读取数据&#xff0c;怎样设置条件&#xff0c;从数据库中查询数据&#xff1f; 本文基于mongodb的官方文档&#xff0c;整理出find命…

​电脑技巧:​笔记本电脑电流声的原因和解决方案

目录 一、音频设备接口接触不良 二、笔记本电源问题 三、笔记本电脑驱动程序问题 四、音频硬件问题 五、操作系统内部电磁干扰 六、最后总结 大家在日常生活当中&#xff0c;笔记本电脑已经成为我们工作、学习和娱乐的重要工具。但有时我们在使用过程中可能会遇到一个令人…

机器学习中的隐马尔可夫模型及Python实现示例

隐马尔可夫模型&#xff08;HMM&#xff09;是一种统计模型&#xff0c;用于描述观测序列和隐藏状态序列之间的概率关系。它通常用于生成观测值的底层系统或过程未知或隐藏的情况&#xff0c;因此它被称为“隐马尔可夫模型”。 它用于根据生成数据的潜在隐藏过程来预测未来的观…

移动通信原理与关键技术学习(4)

1.小尺度衰落 Small-Scale Fading 由于收到的信号是由通过不同的多径到达的信号的总和&#xff0c;接收信号的增强有一定的减小。 小尺度衰落的特点&#xff1a; 信号强度在很小的传播距离或时间间隔内的快速变化&#xff1b;不同多径信号多普勒频移引起的随机调频&#xff…

代码随想录算法训练营第15天 | 102. 二叉树的层序遍历 + 226. 翻转二叉树 + 101. 对称二叉树

今日内容 102.层序遍历 226.翻转二叉树 101.对称二叉树 102.二叉树的层序遍历 - Medium 题目链接&#xff1a;力扣-102. 二叉树的层序遍历 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&…

Matlab 之数据分布拟合

文章目录 Part.I IntroductionPart.II Distribution Fitter APP 的使用Chap.I APP 简介Chap.II 简单使用 Part.III 通过代码实现分布拟合Chap.I 基于 fitdist 函数Chap.II 获取数据的频率分布后进行曲线拟合 Reference Part.I Introduction 本文主要介绍了如何使用 Matlab 对数…

Xcalibur软件Qual Brower程序的使用

找到Qual Brower&#xff1a;在System>Program里 打开采集的数据文件*.RAW&#xff0c;软件界面主窗口能查看色谱图和质谱图&#xff1a; 1、图形的放大和拷贝、色谱中查看峰的质谱信息&#xff1a; 点亮如图图像右上角的按钮&#xff0c;可以激活该图形并进行操作&#x…

JavaScript日期和时间处理手册

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》 ​ ​ ✨ 前言 日期和时间在应用开发中是非常常用的功能。本文将全面介绍JavaScript中处理日期和时间的方…

专业课128分总分400+南京理工大学818信号系统与数字电路南理工考研经验分享

专业课128分总分400南京理工大学818信号系统与数字电路南理工电光院考研经验分享&#xff0c;希望自己的经历对大家有借鉴。 我是在六月底确认自己保不上研然后专心备考的&#xff0c;时间确实比较紧张。虽然之前暑假看了一点高数&#xff0c;但因为抱有保研的期望&#xff0c…

SPI协议介绍

文章目录 一、硬件连线二、引脚含义三、传输示例四、传输模式 一、硬件连线 二、引脚含义 引脚含义DO&#xff08;MOSI - Master Output Slave Input&#xff09;主机发数据&#xff0c;从机收数据DI&#xff08;MISO - Master Input Slave Output&#xff09;主机收数据&…