Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

πŸ”„ Implement Rotors #240

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
4 changes: 2 additions & 2 deletions Bearded.Utilities.Testing/Geometry/Bivector2Assertions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ public AndConstraint<Bivector2Assertions> NotBe(Bivector2 other, string because
public AndConstraint<Bivector2Assertions> BeApproximately(
Bivector2 other, float precision, string because = "", params object[] becauseArgs)
{
subject.Magnitude.Should().BeApproximately(other.Magnitude, precision, because, becauseArgs);
subject.Xy.Should().BeApproximately(other.Xy, precision, because, becauseArgs);
return new AndConstraint<Bivector2Assertions>(this);
}

[CustomAssertion]
public AndConstraint<Bivector2Assertions> NotBeApproximately(
Bivector2 other, float precision, string because = "", params object[] becauseArgs)
{
subject.Magnitude.Should().NotBeApproximately(other.Magnitude, precision, because, becauseArgs);
subject.Xy.Should().NotBeApproximately(other.Xy, precision, because, becauseArgs);
return new AndConstraint<Bivector2Assertions>(this);
}
}
39 changes: 39 additions & 0 deletions Bearded.Utilities.Tests/Assertions/Vector3Assertions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using FluentAssertions;
using FluentAssertions.Execution;
using OpenTK.Mathematics;

namespace Bearded.Utilities.Tests.Assertions
{
sealed class Vector3Assertions
{
private readonly Vector3 subject;

public Vector3Assertions(Vector3 subject)
{
this.subject = subject;
}

[CustomAssertion]
public AndConstraint<Vector3Assertions> BeApproximately(
Vector3 expectedValue,
float precision,
string because = "",
params object[] becauseArgs)
{
var xDifference = Math.Abs(subject.X - expectedValue.X);
var yDifference = Math.Abs(subject.Y - expectedValue.Y);
var zDifference = Math.Abs(subject.Z - expectedValue.Z);

Execute.Assertion
.BecauseOf(because, becauseArgs)
.ForCondition(xDifference <= precision && yDifference <= precision && zDifference <= precision)
.FailWith(
"Expected {context:value} to be approximately {1} +/- {2}{reason}, " +
"but {0}'s coordinates differed by {3} (x), {4} (y), and {5} (z).",
subject, expectedValue, precision, xDifference, yDifference, zDifference);

return new AndConstraint<Vector3Assertions>(this);
}
}
}
9 changes: 9 additions & 0 deletions Bearded.Utilities.Tests/Assertions/Vector3Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using OpenTK.Mathematics;

namespace Bearded.Utilities.Tests.Assertions
{
static class Vector3Extensions
{
public static Vector3Assertions Should(this Vector3 subject) => new Vector3Assertions(subject);
}
}
73 changes: 68 additions & 5 deletions Bearded.Utilities.Tests/Geometry/Bivector2Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Bearded.Utilities.Tests.Geometry;

public sealed class Bivector2Tests
{
private const float epsilon = 1E-6f;
private const float epsilon = 1E-3f;

public Bivector2Tests()
{
Expand Down Expand Up @@ -63,8 +63,52 @@ public void WedgeIsAntiSymmetric(Vector2 left, Vector2 right)
wedge1.Should().Be(-wedge2);
}

[Fact]
public void UnitBivectorHasMagnitudeOne()
{
Bivector2.Unit.Magnitude.Should().BeApproximately(1, epsilon);
Bivector2.Unit.MagnitudeSquared.Should().BeApproximately(1, epsilon);
}

[Fact]
public void ZeroBivectorHasMagnitudeZero()
{
Bivector2.Zero.Magnitude.Should().BeApproximately(0, epsilon);
Bivector2.Zero.MagnitudeSquared.Should().BeApproximately(0, epsilon);
}

[Property]
public void AddingBivectorsAddsMagnitudes(float f1, float f2)
public void NormalizedNonZeroBivectorHasMagnitudeOne(float xy)
{
var bivector = new Bivector2(xy);
if (bivector == Bivector2.Zero) return;

var normalized = bivector.Normalized();

normalized.Magnitude.Should().BeApproximately(1, epsilon);
normalized.MagnitudeSquared.Should().BeApproximately(1, epsilon);
}

[Fact]
public void NormalizedZeroBivectorIsZeroBivector()
{
var bivector = Bivector2.Zero;

bivector.Normalized().Should().Be(bivector);
}

[Property]
public void NormalizedBivectorRetainsSign(float xy)
{
var bivector = new Bivector2(xy);

var normalized = bivector.Normalized();

MathF.Sign(bivector.Xy).Should().Be(MathF.Sign(normalized.Xy));
}

[Property]
public void AddingBivectorsAddsComponents(float f1, float f2)
{
var bivector1 = new Bivector2(f1);
var bivector2 = new Bivector2(f2);
Expand All @@ -74,7 +118,7 @@ public void AddingBivectorsAddsMagnitudes(float f1, float f2)
}

[Property]
public void SubtractingBivectorsSubtractsMagnitudes(float f1, float f2)
public void SubtractingBivectorsSubtractsComponents(float f1, float f2)
{
var bivector1 = new Bivector2(f1);
var bivector2 = new Bivector2(f2);
Expand All @@ -84,7 +128,26 @@ public void SubtractingBivectorsSubtractsMagnitudes(float f1, float f2)
}

[Property]
public void BivectorsWithSameMagnitudeAreEqual(float magnitude)
public void ScalingBivectorScalesItsComponents(float xy, float scalar)
{
var bivector = new Bivector2(xy);
var scaled = scalar * bivector;

scaled.Xy.Should().BeApproximately(xy * scalar, epsilon);
}

[Property]
public void DividingBivectorByScalarDividesItsComponents(float xy, float divider)
{
if (divider == 0) return;
var bivector = new Bivector2(xy);
var scaled = bivector / divider;

scaled.Xy.Should().BeApproximately(xy / divider, epsilon);
}

[Property]
public void BivectorsWithSameComponentsAreEqual(float magnitude)
{
var bivector1 = new Bivector2(magnitude);
var bivector2 = new Bivector2(magnitude);
Expand All @@ -96,7 +159,7 @@ public void BivectorsWithSameMagnitudeAreEqual(float magnitude)
}

[Property]
public void BivectorsWithDifferentMagnitudeAreNotEqual(float f1, float f2)
public void BivectorsWithDifferentComponentsAreNotEqual(float f1, float f2)
{
// ReSharper disable once CompareOfFloatsByEqualityOperator
if (f1 == f2) f2++;
Expand Down
97 changes: 96 additions & 1 deletion Bearded.Utilities.Tests/Geometry/Bivector3Tests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Collections.Generic;
using Bearded.Utilities.Geometry;
using Bearded.Utilities.Testing.Geometry;
using Bearded.Utilities.Tests.Generators;
Expand All @@ -11,7 +12,7 @@ namespace Bearded.Utilities.Tests.Geometry;

public sealed class Bivector3Tests
{
private const float epsilon = 1E-6f;
private const float epsilon = 1E-3f;

public Bivector3Tests()
{
Expand Down Expand Up @@ -62,6 +63,77 @@ public void WedgeIsAntiSymmetric(Vector3 left, Vector3 right)
wedge1.Should().Be(-wedge2);
}

[Property]
public void FromAxisCreatesBivectorWithSameMagnitudeAsVector(Vector3 axis)
{
var bivector = Bivector3.FromAxis(axis);

bivector.Magnitude.Should().BeApproximately(axis.Length, epsilon);
}

[Property]
public void FromAxisRetainsSign(Vector3 axis)
{
var bivector = Bivector3.FromAxis(axis);
var reverseBivector = Bivector3.FromAxis(-axis);

bivector.Should().BeApproximately(-reverseBivector, epsilon);
}

[Theory]
[MemberData(nameof(UnitVectorsWithOrthogonalPlanes))]
public void FromAxisReturnsOrthogonalPlaneToUnitVectors(Vector3 axis, Bivector3 expectedBivector)
{
var bivector = Bivector3.FromAxis(axis);

bivector.Should().BeApproximately(expectedBivector, epsilon);
}

public static IEnumerable<object[]> UnitVectorsWithOrthogonalPlanes()
{
yield return new object[] { Vector3.UnitX, Bivector3.UnitYz };
yield return new object[] { Vector3.UnitY, -Bivector3.UnitXz };
yield return new object[] { Vector3.UnitZ, Bivector3.UnitXy };
}

[Fact]
public void UnitBivectorsHaveMagnitudeOne()
{
Bivector3.UnitXy.Magnitude.Should().BeApproximately(1, epsilon);
Bivector3.UnitXy.MagnitudeSquared.Should().BeApproximately(1, epsilon);
Bivector3.UnitYz.Magnitude.Should().BeApproximately(1, epsilon);
Bivector3.UnitYz.MagnitudeSquared.Should().BeApproximately(1, epsilon);
Bivector3.UnitXz.Magnitude.Should().BeApproximately(1, epsilon);
Bivector3.UnitXz.MagnitudeSquared.Should().BeApproximately(1, epsilon);
}

[Fact]
public void ZeroBivectorHasMagnitudeZero()
{
Bivector3.Zero.Magnitude.Should().BeApproximately(0, epsilon);
Bivector3.Zero.MagnitudeSquared.Should().BeApproximately(0, epsilon);
}

[Property]
public void NormalizedNonZeroBivectorHasMagnitudeOne(float xy, float yz, float xz)
{
var bivector = new Bivector3(xy, yz, xz);
if (bivector == Bivector3.Zero) return;

var normalized = bivector.Normalized();

normalized.Magnitude.Should().BeApproximately(1, epsilon);
normalized.MagnitudeSquared.Should().BeApproximately(1, epsilon);
}

[Fact]
public void NormalizedZeroBivectorIsZeroBivector()
{
var bivector = Bivector3.Zero;

bivector.Normalized().Should().Be(bivector);
}

[Property]
public void AddingBivectorsAddsComponents(float xy1, float xy2, float yz1, float yz2, float xz1, float xz2)
{
Expand All @@ -83,6 +155,29 @@ public void SubtractingBivectorsSubtractsComponents(
sum.Should().BeApproximately(new Bivector3(xy1 - xy2, yz1 - yz2, xz1 - xz2), epsilon);
}

[Property]
public void ScalingBivectorScalesItsComponents(float xy, float yz, float xz, float scalar)
{
var bivector = new Bivector3(xy, yz, xz);
var scaled = scalar * bivector;

scaled.Xy.Should().BeApproximately(xy * scalar, epsilon);
scaled.Yz.Should().BeApproximately(yz * scalar, epsilon);
scaled.Xz.Should().BeApproximately(xz * scalar, epsilon);
}

[Property]
public void DividingBivectorByScalarDividesItsComponents(float xy, float yz, float xz, float divider)
{
if (divider == 0) return;
var bivector = new Bivector3(xy, yz, xz);
var scaled = bivector / divider;

scaled.Xy.Should().BeApproximately(xy / divider, epsilon);
scaled.Yz.Should().BeApproximately(yz / divider, epsilon);
scaled.Xz.Should().BeApproximately(xz / divider, epsilon);
}

[Property]
public void BivectorsWithSameComponentsAreEqual(float xy, float yz, float xz)
{
Expand Down
2 changes: 1 addition & 1 deletion Bearded.Utilities.Tests/Geometry/CircularArc2Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Bearded.Utilities.Tests.Geometry;

public sealed class CircularArc2Tests
{
private const float epsilon = 0.001f;
private const float epsilon = 1E-3f;

public CircularArc2Tests()
{
Expand Down
Loading