Add Quaternion.ToAxisAngle and Quaternion.ToVector3

This commit is contained in:
Oliver Booth 2022-12-06 00:58:15 +00:00
parent b60fdc495b
commit 9d6dbaaa23
No known key found for this signature in database
GPG Key ID: 32A00B35503AF634
3 changed files with 54 additions and 0 deletions

View File

@ -31,6 +31,8 @@
- X10D: Added `PointF.ToSizeF()` - X10D: Added `PointF.ToSizeF()`
- X10D: Added `PointF.ToVector2()` for .NET < 6 - X10D: Added `PointF.ToVector2()` for .NET < 6
- X10D: Added `PopCount()` for built-in integer types - X10D: Added `PopCount()` for built-in integer types
- X10D: Added `Quaternion.ToAxisAngle(out float, out float)`
- X10D: Added `Quaternion.ToVector3()`
- X10D: Added `ReadOnlySpan<char>.CountSubstring(char)` - X10D: Added `ReadOnlySpan<char>.CountSubstring(char)`
- X10D: Added `ReadOnlySpan<char>.CountSubstring(ReadOnlySpan<char>[, StringComparison])` - X10D: Added `ReadOnlySpan<char>.CountSubstring(ReadOnlySpan<char>[, StringComparison])`
- X10D: Added `ReadOnlySpan<T>.Split(T)` - X10D: Added `ReadOnlySpan<T>.Split(T)`

View File

@ -0,0 +1,21 @@
using System.Numerics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Numerics;
namespace X10D.Tests.Numerics;
[TestClass]
public class QuaternionTests
{
[TestMethod]
public void ToAxisAngle_ShouldGiveAngle180VectorZero_GivenQuaternion()
{
Vector3 axis = Vector3.UnitY;
const float angle = MathF.PI;
var quaternion = Quaternion.CreateFromAxisAngle(axis, angle);
(Vector3 Axis, float Angle) axisAngle = quaternion.ToAxisAngle();
Assert.AreEqual(axis, axisAngle.Axis);
Assert.AreEqual(angle, axisAngle.Angle);
}
}

View File

@ -38,4 +38,35 @@ public static class QuaternionExtensions
(xz - wy) * px + (yz + wx) * py + (1.0f - (xx + yy)) * pz (xz - wy) * px + (yz + wx) * py + (1.0f - (xx + yy)) * pz
); );
} }
/// <summary>
/// Converts this quaternion to an axis/angle pair.
/// </summary>
/// <param name="value">The quaternion to convert.</param>
/// <returns>A tuple containing the converted axis, and the angle in radians.</returns>
public static (Vector3 Axis, float Angle) ToAxisAngle(this in Quaternion value)
{
float angle = 2.0f * MathF.Acos(value.W);
Vector3 axis = Vector3.Normalize(new Vector3(value.X, value.Y, value.Z));
return (axis, angle);
}
/// <summary>
/// Converts this quaternion to a <see cref="Vector3" /> containing an Euler representation of the rotation.
/// </summary>
/// <param name="value">The quaternion to convert.</param>
/// <returns>The Euler representation of <paramref name="value" />, in radians.</returns>
public static Vector3 ToVector3(this in Quaternion value)
{
Quaternion normalized = Quaternion.Normalize(value);
float qx = normalized.X;
float qy = normalized.Y;
float qz = normalized.Z;
float qw = normalized.W;
float x = MathF.Atan2(2 * (qx * qw - qy * qz), 1 - 2 * (qx * qx + qz * qz));
float y = MathF.Asin(2 * (qx * qz + qy * qw));
float z = MathF.Atan2(2 * (qz * qw - qx * qy), 1 - 2 * (qy * qy + qz * qz));
return new Vector3(x, y, z);
}
} }