Add vector and point component rounding (#65)

This commit is contained in:
Oliver Booth 2022-07-13 12:09:37 +01:00
parent efa5145836
commit 46bfa17b93
No known key found for this signature in database
GPG Key ID: 32A00B35503AF634
15 changed files with 405 additions and 0 deletions

View File

@ -12,6 +12,7 @@
- X10D: Added `Point.ToSize()`
- X10D: Added `Point.ToSizeF()`
- X10D: Added `Point.ToVector2()`
- X10D: Added `PointF.Round([float])`
- X10D: Added `PointF.ToSizeF()`
- X10D: Added `PointF.ToVector2()` for .NET < 6
- X10D: Added `PopCount()` for built-in integer types
@ -22,10 +23,13 @@
- X10D: Added `Quaternion.Multiply(Vector3)` - this functions as an equivalent to Unity's `Quaternion * Vector3` operator
- X10D: Added `Vector2.Deconstruct()`
- X10D: Added `Vector2.IsOnLine(LineF)`, `Vector2.IsOnLine(PointF, PointF)`, and `Vector2.IsOnLine(Vector2, Vector2)`
- X10D: Added `Vector2.Round([float])`
- X10D: Added `Vector2.ToPointF()`
- X10D: Added `Vector2.ToSizeF()`
- X10D: Added `Vector3.Deconstruct()`
- X10D: Added `Vector3.Round([float])`
- X10D: Added `Vector4.Deconstruct()`
- X10D: Added `Vector4.Round([float])`
- X10D.Unity: Added `DebugEx`, which mimics `UnityEngine.Debug` while offering more useful primitive drawing methods
- X10D.Unity: Added `System.Drawing.Color.ToUnityColor()`
- X10D.Unity: Added `System.Drawing.Color.ToUnityColor32()`
@ -46,6 +50,7 @@
- X10D.Unity: Added `Vector2.Deconstruct()`
- X10D.Unity: Added `Vector2.IsOnLine(LineF)`, `Vector2.IsOnLine(PointF, PointF)`, and `Vector2.IsOnLine(Vector2, Vector2)`
- X10D.Unity: Added `Vector2Int.IsOnLine(LineF)`, `Vector2Int.IsOnLine(PointF, PointF)`, `Vector2Int.IsOnLine(Vector2, Vector2)`, and `Vector2Int.IsOnLine(Vector2Int, Vector2Int)`
- X10D.Unity: Added `Vector2.Round([float])`
- X10D.Unity: Added `Vector2.ToSystemPointF()`
- X10D.Unity: Added `Vector2.ToSystemSizeF()`
- X10D.Unity: Added `Vector2Int.Deconstruct()`
@ -55,12 +60,14 @@
- X10D.Unity: Added `Vector2Int.WithX()`
- X10D.Unity: Added `Vector2Int.WithY()`
- X10D.Unity: Added `Vector3.Deconstruct()`
- X10D.Unity: Added `Vector3.Round([float])`
- X10D.Unity: Added `Vector3Int.Deconstruct()`
- X10D.Unity: Added `Vector3Int.ToSystemVector()`
- X10D.Unity: Added `Vector3Int.WithX()`
- X10D.Unity: Added `Vector3Int.WithY()`
- X10D.Unity: Added `Vector3Int.WithZ()`
- X10D.Unity: Added `Vector4.Deconstruct()`
- X10D.Unity: Added `Vector4.Round([float])`
### Changed
- X10D.Unity: Obsolesced `Singleton<T>`

View File

@ -8,6 +8,26 @@ namespace X10D.Tests.Drawing;
[TestClass]
public class PointFTests
{
[TestMethod]
public void Round_ShouldRoundToNearestInteger_GivenNoParameters()
{
var point = new PointF(1.5f, 2.6f);
var rounded = point.Round();
Assert.AreEqual(2, rounded.X);
Assert.AreEqual(3, rounded.Y);
}
[TestMethod]
public void Round_ShouldRoundToNearest10_GivenPrecision10()
{
var point = new PointF(1.5f, 25.2f);
var rounded = point.Round(10);
Assert.AreEqual(0, rounded.X);
Assert.AreEqual(30, rounded.Y);
}
[TestMethod]
public void ToSizeF_ShouldReturnSize_WithEquivalentMembers()
{

View File

@ -18,6 +18,26 @@ public class Vector2Tests
Assert.AreEqual(2, y);
}
[TestMethod]
public void Round_ShouldRoundToNearestInteger_GivenNoParameters()
{
var vector = new Vector2(1.5f, 2.6f);
var rounded = vector.Round();
Assert.AreEqual(2, rounded.X);
Assert.AreEqual(3, rounded.Y);
}
[TestMethod]
public void Round_ShouldRoundToNearest10_GivenPrecision10()
{
var vector = new Vector2(1.5f, 25.2f);
var rounded = vector.Round(10);
Assert.AreEqual(0, rounded.X);
Assert.AreEqual(30, rounded.Y);
}
[TestMethod]
public void ToPointF_ShouldReturnPoint_WithEquivalentMembers()
{

View File

@ -18,6 +18,28 @@ public class Vector3Tests
Assert.AreEqual(3, z);
}
[TestMethod]
public void Round_ShouldRoundToNearestInteger_GivenNoParameters()
{
var vector = new Vector3(1.5f, 2.6f, -5.2f);
var rounded = vector.Round();
Assert.AreEqual(2, rounded.X);
Assert.AreEqual(3, rounded.Y);
Assert.AreEqual(-5, rounded.Z);
}
[TestMethod]
public void Round_ShouldRoundToNearest10_GivenPrecision10()
{
var vector = new Vector3(1.5f, 25.2f, -12.5f);
var rounded = vector.Round(10);
Assert.AreEqual(0, rounded.X);
Assert.AreEqual(30, rounded.Y);
Assert.AreEqual(-10, rounded.Z);
}
[TestMethod]
public void WithX_ShouldReturnVectorWithNewX_GivenVector()
{

View File

@ -19,6 +19,30 @@ public class Vector4Tests
Assert.AreEqual(4, w);
}
[TestMethod]
public void Round_ShouldRoundToNearestInteger_GivenNoParameters()
{
var vector = new Vector4(1.5f, 2.6f, -5.2f, 0.3f);
var rounded = vector.Round();
Assert.AreEqual(2, rounded.X);
Assert.AreEqual(3, rounded.Y);
Assert.AreEqual(-5, rounded.Z);
Assert.AreEqual(0, rounded.W);
}
[TestMethod]
public void Round_ShouldRoundToNearest10_GivenPrecision10()
{
var vector = new Vector4(1.5f, 25.2f, -12.5f, 101.2f);
var rounded = vector.Round(10);
Assert.AreEqual(0, rounded.X);
Assert.AreEqual(30, rounded.Y);
Assert.AreEqual(-10, rounded.Z);
Assert.AreEqual(100, rounded.W);
}
[TestMethod]
public void WithW_ShouldReturnVectorWithNewW_GivenVector()
{

View File

@ -22,6 +22,30 @@ namespace X10D.Unity.Tests.Numerics
yield break;
}
[UnityTest]
public IEnumerator Round_ShouldRoundToNearestInteger_GivenNoParameters()
{
var vector = new Vector2(1.5f, 2.6f);
var rounded = vector.Round();
Assert.AreEqual(2, rounded.x);
Assert.AreEqual(3, rounded.y);
yield break;
}
[UnityTest]
public IEnumerator Round_ShouldRoundToNearest10_GivenPrecision10()
{
var vector = new Vector2(1.5f, 25.2f);
var rounded = vector.Round(10);
Assert.AreEqual(0, rounded.x);
Assert.AreEqual(30, rounded.y);
yield break;
}
[UnityTest]
public IEnumerator ToSystemPointF_ShouldReturnPoint_WithEquivalentMembers()
{

View File

@ -23,6 +23,32 @@ namespace X10D.Unity.Tests.Numerics
yield break;
}
[UnityTest]
public IEnumerator Round_ShouldRoundToNearestInteger_GivenNoParameters()
{
var vector = new Vector3(1.5f, 2.6f, -5.2f);
var rounded = vector.Round();
Assert.AreEqual(2, rounded.x);
Assert.AreEqual(3, rounded.y);
Assert.AreEqual(-5, rounded.z);
yield break;
}
[UnityTest]
public IEnumerator Round_ShouldRoundToNearest10_GivenPrecision10()
{
var vector = new Vector3(1.5f, 25.2f, -12.5f);
var rounded = vector.Round(10);
Assert.AreEqual(0, rounded.x);
Assert.AreEqual(30, rounded.y);
Assert.AreEqual(-10, rounded.z);
yield break;
}
[UnityTest]
public IEnumerator ToSystemVector_ShouldReturnVector_WithEqualComponents()
{

View File

@ -24,6 +24,34 @@ namespace X10D.Unity.Tests.Numerics
yield break;
}
[UnityTest]
public IEnumerator Round_ShouldRoundToNearestInteger_GivenNoParameters()
{
var vector = new Vector4(1.5f, 2.6f, -5.2f, 0.3f);
var rounded = vector.Round();
Assert.AreEqual(2, rounded.x);
Assert.AreEqual(3, rounded.y);
Assert.AreEqual(-5, rounded.z);
Assert.AreEqual(0, rounded.w);
yield break;
}
[UnityTest]
public IEnumerator Round_ShouldRoundToNearest10_GivenPrecision10()
{
var vector = new Vector4(1.5f, 25.2f, -12.5f, 101.2f);
var rounded = vector.Round(10);
Assert.AreEqual(0, rounded.x);
Assert.AreEqual(30, rounded.y);
Assert.AreEqual(-10, rounded.z);
Assert.AreEqual(100, rounded.w);
yield break;
}
[UnityTest]
public IEnumerator ToSystemVector_ShouldReturnVector_WithEqualComponents()
{

View File

@ -3,6 +3,7 @@ using System.Drawing;
using System.Runtime.CompilerServices;
using UnityEngine;
using X10D.Drawing;
using X10D.Math;
using X10D.Numerics;
namespace X10D.Unity.Numerics;
@ -74,6 +75,33 @@ public static class Vector2Extensions
return point.ToSystemVector().IsOnLine(start.ToSystemVector(), end.ToSystemVector());
}
/// <summary>
/// Rounds the components in the current <see cref="Vector2" /> to the nearest integer.
/// </summary>
/// <param name="vector">The vector whose components to round.</param>
/// <returns>The rounded vector.</returns>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Round(this Vector2 vector)
{
return vector.Round(1.0f);
}
/// <summary>
/// Rounds the components in the current <see cref="Vector2" /> to the nearest multiple of a specified number.
/// </summary>
/// <param name="vector">The vector whose components to round.</param>
/// <param name="nearest">The nearest multiple to which the components should be rounded.</param>
/// <returns>The rounded vector.</returns>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Round(this Vector2 vector, float nearest)
{
float x = vector.x.Round(nearest);
float y = vector.y.Round(nearest);
return new Vector2(x, y);
}
/// <summary>
/// Converts the current <see cref="Vector2" /> into a <see cref="PointF" />.
/// </summary>

View File

@ -1,6 +1,7 @@
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
using UnityEngine;
using X10D.Math;
namespace X10D.Unity.Numerics;
@ -23,6 +24,34 @@ public static class Vector3Extensions
z = vector.z;
}
/// <summary>
/// Rounds the components in the current <see cref="Vector3" /> to the nearest integer.
/// </summary>
/// <param name="vector">The vector whose components to round.</param>
/// <returns>The rounded vector.</returns>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Round(this Vector3 vector)
{
return vector.Round(1.0f);
}
/// <summary>
/// Rounds the components in the current <see cref="Vector3" /> to the nearest multiple of a specified number.
/// </summary>
/// <param name="vector">The vector whose components to round.</param>
/// <param name="nearest">The nearest multiple to which the components should be rounded.</param>
/// <returns>The rounded vector.</returns>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Round(this Vector3 vector, float nearest)
{
float x = vector.x.Round(nearest);
float y = vector.y.Round(nearest);
float z = vector.z.Round(nearest);
return new Vector3(x, y, z);
}
/// <summary>
/// Converts the current vector to a <see cref="System.Numerics.Vector3" />.
/// </summary>

View File

@ -1,6 +1,7 @@
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
using UnityEngine;
using X10D.Math;
namespace X10D.Unity.Numerics;
@ -25,6 +26,35 @@ public static class Vector4Extensions
w = vector.w;
}
/// <summary>
/// Rounds the components in the current <see cref="Vector4" /> to the nearest integer.
/// </summary>
/// <param name="vector">The vector whose components to round.</param>
/// <returns>The rounded vector.</returns>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 Round(this Vector4 vector)
{
return vector.Round(1.0f);
}
/// <summary>
/// Rounds the components in the current <see cref="Vector4" /> to the nearest multiple of a specified number.
/// </summary>
/// <param name="vector">The vector whose components to round.</param>
/// <param name="nearest">The nearest multiple to which the components should be rounded.</param>
/// <returns>The rounded vector.</returns>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 Round(this Vector4 vector, float nearest)
{
float x = vector.x.Round(nearest);
float y = vector.y.Round(nearest);
float z = vector.z.Round(nearest);
float w = vector.w.Round(nearest);
return new Vector4(x, y, z, w);
}
/// <summary>
/// Converts the current vector to a <see cref="System.Numerics.Vector4" />.
/// </summary>

View File

@ -2,6 +2,7 @@
using System.Drawing;
using System.Numerics;
using System.Runtime.CompilerServices;
using X10D.Math;
namespace X10D.Drawing;
@ -75,6 +76,41 @@ public static class PointFExtensions
return point.IsOnLine(new LineF(start, end));
}
/// <summary>
/// Rounds the components in the current <see cref="PointF" /> to the nearest integer.
/// </summary>
/// <param name="point">The point whose components to round.</param>
/// <returns>The rounded point.</returns>
[Pure]
#if NETSTANDARD2_1
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
#endif
public static PointF Round(this PointF point)
{
return point.Round(1.0f);
}
/// <summary>
/// Rounds the components in the current <see cref="PointF" /> to the nearest multiple of a specified number.
/// </summary>
/// <param name="point">The point whose components to round.</param>
/// <param name="nearest">The nearest multiple to which the components should be rounded.</param>
/// <returns>The rounded point.</returns>
[Pure]
#if NETSTANDARD2_1
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
#endif
public static PointF Round(this PointF point, float nearest)
{
float x = point.X.Round(nearest);
float y = point.Y.Round(nearest);
return new PointF(x, y);
}
/// <summary>
/// Converts the current <see cref="PointF" /> to a <see cref="SizeF" />.
/// </summary>

View File

@ -3,6 +3,7 @@ using System.Drawing;
using System.Numerics;
using System.Runtime.CompilerServices;
using X10D.Drawing;
using X10D.Math;
namespace X10D.Numerics;
@ -88,6 +89,41 @@ public static class Vector2Extensions
return point.IsOnLine(new LineF(start, end));
}
/// <summary>
/// Rounds the components in the current <see cref="Vector2" /> to the nearest integer.
/// </summary>
/// <param name="vector">The vector whose components to round.</param>
/// <returns>The rounded vector.</returns>
[Pure]
#if NETSTANDARD2_1
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
#endif
public static Vector2 Round(this Vector2 vector)
{
return vector.Round(1.0f);
}
/// <summary>
/// Rounds the components in the current <see cref="Vector2" /> to the nearest multiple of a specified number.
/// </summary>
/// <param name="vector">The vector whose components to round.</param>
/// <param name="nearest">The nearest multiple to which the components should be rounded.</param>
/// <returns>The rounded vector.</returns>
[Pure]
#if NETSTANDARD2_1
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
#endif
public static Vector2 Round(this Vector2 vector, float nearest)
{
float x = vector.X.Round(nearest);
float y = vector.Y.Round(nearest);
return new Vector2(x, y);
}
/// <summary>
/// Converts the current <see cref="Vector2" /> to a <see cref="PointF" />.
/// </summary>

View File

@ -1,6 +1,7 @@
using System.Diagnostics.Contracts;
using System.Numerics;
using System.Runtime.CompilerServices;
using X10D.Math;
namespace X10D.Numerics;
@ -23,6 +24,42 @@ public static class Vector3Extensions
z = vector.Z;
}
/// <summary>
/// Rounds the components in the current <see cref="Vector3" /> to the nearest integer.
/// </summary>
/// <param name="vector">The vector whose components to round.</param>
/// <returns>The rounded vector.</returns>
[Pure]
#if NETSTANDARD2_1
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
#endif
public static Vector3 Round(this Vector3 vector)
{
return vector.Round(1.0f);
}
/// <summary>
/// Rounds the components in the current <see cref="Vector3" /> to the nearest multiple of a specified number.
/// </summary>
/// <param name="vector">The vector whose components to round.</param>
/// <param name="nearest">The nearest multiple to which the components should be rounded.</param>
/// <returns>The rounded vector.</returns>
[Pure]
#if NETSTANDARD2_1
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
#endif
public static Vector3 Round(this Vector3 vector, float nearest)
{
float x = vector.X.Round(nearest);
float y = vector.Y.Round(nearest);
float z = vector.Z.Round(nearest);
return new Vector3(x, y, z);
}
/// <summary>
/// Returns a vector whose Y and Z components are the same as the specified vector, and whose X component is a new value.
/// </summary>

View File

@ -1,6 +1,7 @@
using System.Diagnostics.Contracts;
using System.Numerics;
using System.Runtime.CompilerServices;
using X10D.Math;
namespace X10D.Numerics;
@ -25,6 +26,43 @@ public static class Vector4Extensions
w = vector.W;
}
/// <summary>
/// Rounds the components in the current <see cref="Vector4" /> to the nearest integer.
/// </summary>
/// <param name="vector">The vector whose components to round.</param>
/// <returns>The rounded vector.</returns>
[Pure]
#if NETSTANDARD2_1
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
#endif
public static Vector4 Round(this Vector4 vector)
{
return vector.Round(1.0f);
}
/// <summary>
/// Rounds the components in the current <see cref="Vector4" /> to the nearest multiple of a specified number.
/// </summary>
/// <param name="vector">The vector whose components to round.</param>
/// <param name="nearest">The nearest multiple to which the components should be rounded.</param>
/// <returns>The rounded vector.</returns>
[Pure]
#if NETSTANDARD2_1
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#else
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
#endif
public static Vector4 Round(this Vector4 vector, float nearest)
{
float x = vector.X.Round(nearest);
float y = vector.Y.Round(nearest);
float z = vector.Z.Round(nearest);
float w = vector.W.Round(nearest);
return new Vector4(x, y, z, w);
}
/// <summary>
/// Returns a vector whose Y, Z, and W components are the same as the specified vector, and whose X component is a new
/// value.