Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Math3D/Extensions/FloatExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// © XIV-Tools.
// Licensed under the MIT license.

namespace XivToolsWpf.Math3D.Extensions;

using System;
using System.Runtime.CompilerServices;

public static class FloatExtensions
{
/// <summary>
/// Determines whether two floating-point numbers are approximately equal within a specified error margin.
/// </summary>
/// <param name="a">The first floating-point number.</param>
/// <param name="b">The second floating-point number.</param>
/// <param name="errorMargin">The acceptable error margin for the comparison.</param>
/// <returns>True if the absolute difference between the two numbers is less than the error margin; otherwise, false.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsApproximately(this float a, float b, float errorMargin) => MathF.Abs(a - b) < errorMargin;
}
88 changes: 88 additions & 0 deletions Math3D/Extensions/Matrix4x4Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// © XIV-Tools.
// Licensed under the MIT license.

namespace XivToolsWpf.Math3D.Extensions;

using System.Numerics;
using System.Runtime.CompilerServices;
using System.Windows.Media.Media3D;

public static class Matrix4x4Extensions
{
/// <summary>
/// Determines whether two matrices are approximately equal within a specified error margin.
/// </summary>
/// <remarks>
/// This method is useful for comparing matrices when minor floating-point inaccuracies are
/// expected. It performs an element-wise comparison using the specified error margin.
/// </remarks>
/// <param name="lhs">The first matrix to compare.</param>
/// <param name="rhs">The second matrix to compare.</param>
/// <param name="errorMargin">
/// The maximum allowed difference between corresponding elements for the matrices to be
/// considered approximately equal. Must be greater than or equal to 0. The default is 0.0001.
/// </param>
/// <returns>
/// true if all corresponding elements of the matrices differ by no more than the
/// specified error margin; otherwise, false.
/// </returns>
public static bool IsApproximately(this Matrix4x4 lhs, Matrix4x4 rhs, float errorMargin = 0.0001f)
{
return lhs.M11.IsApproximately(rhs.M11, errorMargin)
&& lhs.M12.IsApproximately(rhs.M12, errorMargin)
&& lhs.M13.IsApproximately(rhs.M13, errorMargin)
&& lhs.M14.IsApproximately(rhs.M14, errorMargin)
&& lhs.M21.IsApproximately(rhs.M21, errorMargin)
&& lhs.M22.IsApproximately(rhs.M22, errorMargin)
&& lhs.M23.IsApproximately(rhs.M23, errorMargin)
&& lhs.M24.IsApproximately(rhs.M24, errorMargin)
&& lhs.M31.IsApproximately(rhs.M31, errorMargin)
&& lhs.M32.IsApproximately(rhs.M32, errorMargin)
&& lhs.M33.IsApproximately(rhs.M33, errorMargin)
&& lhs.M34.IsApproximately(rhs.M34, errorMargin)
&& lhs.M41.IsApproximately(rhs.M41, errorMargin)
&& lhs.M42.IsApproximately(rhs.M42, errorMargin)
&& lhs.M43.IsApproximately(rhs.M43, errorMargin)
&& lhs.M44.IsApproximately(rhs.M44, errorMargin);
}

/// <summary>
/// Converts a Matrix3D to a Matrix4x4.
/// </summary>
/// <param name="m">
/// The matrix to convert.
/// </param>
/// <returns>
/// The converted Matrix4x4.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix4x4 ToMatrix4x4(this Matrix3D m)
{
return new Matrix4x4(
(float)m.M11, (float)m.M12, (float)m.M13, (float)m.M14,
(float)m.M21, (float)m.M22, (float)m.M23, (float)m.M24,
(float)m.M31, (float)m.M32, (float)m.M33, (float)m.M34,
(float)m.OffsetX, (float)m.OffsetY, (float)m.OffsetZ, (float)m.M44);
}

/// <summary>
/// Converts a Matrix4x4 to a Matrix3D.
/// </summary>
/// <param name="m">
/// The matrix to convert.
/// </param>
/// <returns>
/// The converted Matrix3D.
/// </returns>

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3D ToMatrix3D(this Matrix4x4 m)
{
return new Matrix3D(
m.M11, m.M12, m.M13, m.M14,
m.M21, m.M22, m.M23, m.M24,
m.M31, m.M32, m.M33, m.M34,
m.M41, m.M42, m.M43, m.M44);
}
}

18 changes: 4 additions & 14 deletions Math3D/Extensions/VectorExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ public static class VectorExtensions
/// </returns>
public static bool IsApproximately(this Vector3 lhs, Vector3 rhs, float errorMargin = 0.001f)
{
return IsApproximately(lhs.X, rhs.X, errorMargin)
&& IsApproximately(lhs.Y, rhs.Y, errorMargin)
&& IsApproximately(lhs.Z, rhs.Z, errorMargin);
return lhs.X.IsApproximately(rhs.X, errorMargin)
&& lhs.Y.IsApproximately(rhs.Y, errorMargin)
&& lhs.Z.IsApproximately(rhs.Z, errorMargin);
}

/// <summary>
Expand Down Expand Up @@ -120,7 +120,7 @@ public static System.Windows.Media.Media3D.Vector3D ToMedia3DVector(this Vector3
/// </summary>
/// <param name="self">The Media3D Vector3D to be converted.</param>
/// <returns>A new System.Numerics Vector3 with the same components as the Media3D Vector3D.</returns>
public static Vector3 FromMedia3DQuaternion(this System.Windows.Media.Media3D.Vector3D self)
public static Vector3 FromMedia3DVector(this System.Windows.Media.Media3D.Vector3D self)
{
return new Vector3((float)self.X, (float)self.Y, (float)self.Z);
}
Expand Down Expand Up @@ -218,16 +218,6 @@ private static float NormalizeAngle(float angle)
return angle;
}

/// <summary>
/// Determines whether two floating-point numbers are approximately equal within a specified error margin.
/// </summary>
/// <param name="a">The first floating-point number.</param>
/// <param name="b">The second floating-point number.</param>
/// <param name="errorMargin">The acceptable error margin for the comparison.</param>
/// <returns>True if the absolute difference between the two numbers is less than the error margin; otherwise, false.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool IsApproximately(float a, float b, float errorMargin) => MathF.Abs(a - b) < errorMargin;

/// <summary>
/// Determines whether a nullable float is valid (i.e., not null, not infinity, and not NaN).
/// </summary>
Expand Down
Loading