当前位置: 首页 > 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

相关文章:

  • 微信原生小程序自定义封装组件(以导航navbar为例)
  • Java脚本引擎Nashron中使用继承实现多线程编程
  • vue自适应高度(缩放浏览器)
  • 测试工程师的linux 命令学习(持续更新中)
  • 简明docker快速入门并实践方法
  • 动态路由vue-router
  • 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 入门需要了解的概念