当前位置: 首页 > article >正文

Unity计算二维向量夹角余弦值和正弦值的优化方法参考

        如果不考虑优化问题,计算两个向量的余弦值或者正弦值可以直接使用类似的方法:

[SerializeField]
Vector2 v1, v2;

void Start()
{
    float valCos = Mathf.Acos(Vector2.SignedAngle(v1, v2));
    float valSin = Mathf.Asin(Vector2.SignedAngle(v1, v2));
}

        但是上面的Vector2.SignedAngle方法实际上是先计算出余弦值再根据余弦值计算角度,然后我们再根据角度计算出余弦值,这个太绕了,属于脱那什么放那什么的做法。

        从数学原理上来说,计算夹角余弦的思路如下:

将公式代入得到:

但是这里面出现了两次开方运算,可以变换成如下形式:

这样就只需要一次开方运算,对应代码参考如下:

	bool TryVectorAcos(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, out float acos)
	{
		acos = 0;
		if (Mathf.Approximately((p2 - p1).sqrMagnitude, 0) || Mathf.Approximately((p4 - p3).sqrMagnitude, 0)) return false;

		float ax = p2.x - p1.x;
		float ay = p2.y - p1.y;
		float bx = p4.x - p3.x;
		float by = p4.y - p3.y;

		acos = (ax * bx + ay * by) / (Mathf.Sqrt((ax * ax + ay * ay) * (bx * bx + by * by)));

		return true;
	}

带入上面的余弦值公式可得到:

但这个公式也出现了两次开方运算,可以将该公式变换成如下形式:

这样也是只需要一次开方运算就好,对应代码参考如下:

	bool TryVectorAsin(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, out float asin)
	{
		asin = 0;
		if (Mathf.Approximately((p2 - p1).sqrMagnitude, 0) || Mathf.Approximately((p4 - p3).sqrMagnitude, 0)) return false;

		float ax = p2.x - p1.x;
		float ay = p2.y - p1.y;
		float bx = p4.x - p3.x;
		float by = p4.y - p3.y;

		asin = (ax * by - ay * bx) / Mathf.Sqrt((ax * ax + ay * ay) * (bx * bx + by * by));

		return true;
	}

        如果要同时获得正弦值和余弦值,以避免重复计算两个矢量模的积,代码参考如下:

	bool TryVectorAcosAndAsin(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, out float acos, out float asin)
	{
		acos = 0;
		asin = 0;
		if (Mathf.Approximately((p2 - p1).sqrMagnitude, 0) || Mathf.Approximately((p4 - p3).sqrMagnitude, 0)) return false;

		float ax = p2.x - p1.x;
		float ay = p2.y - p1.y;
		float bx = p4.x - p3.x;
		float by = p4.y - p3.y;

		float denominator = Mathf.Sqrt((ax * ax + ay * ay) * (bx * bx + by * by));
		acos = (ax * bx + ay * by) / denominator;
		asin = (ax * by - ay * bx) / denominator;

		return true;
	}


http://www.kler.cn/a/373078.html

相关文章:

  • Java 使用Maven Surefire插件批量运行单元测试
  • solidworks学习6吊环-20241030
  • 大数据-191 Elasticsearch - ES 集群模式 配置启动 规划调优
  • C语言之环形缓冲区概述及实现
  • (蓝桥杯C/C++)——常用库函数
  • Docker-常用命令大全(附命令详解)
  • cmake学习笔记
  • 什么是目标检测?
  • P1037 [NOIP2002 普及组] 产生数
  • Mybatis-18.动态SQL-sqlinclude
  • 【从零开始的LeetCode-算法】3216. 交换后字典序最小的字符串
  • MaskGCT,零样本语音克隆,TTS语音合成,多语言支持(WIN/MAC)
  • mac|maven项目在idea中连接redis
  • 智能合约分享
  • CSS浮雕效果
  • C++: String容器的使用和实现
  • 【MySQL】日志
  • QT中使用图表之QChart概述
  • 排查公网NAT网关中高流量ECS实例
  • 想要分离人声,来试试看这几个方法
  • 使用PE工具箱进行系统安装
  • 企业新闻及产品宣传稿怎么写?有哪些商业财经类报纸杂志或媒体发布?
  • 串口扫盲TTL,TX/TR/GND
  • 统计数据集的TXT、XML及JSON标注文件中各类别/每个标签的数量
  • threejs开源实例-粒子地球
  • ElasticSearch 入门需要了解的概念