Add JSON converters for Vector, Quaternion and Plane types (#4)
* Add JSON converters for Vector, Quaternion and Plane types * Add extension methods to convert between different types * Add license headers * ran formatter --------- Co-authored-by: Adam Hathcock <adam@hathcock.uk>
This commit is contained in:
@@ -0,0 +1,222 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.Runtime.Intrinsics;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Speckle.DoubleNumerics.Tests;
|
||||||
|
|
||||||
|
public class ConversionExtensionsTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void PlaneAsVector4Test()
|
||||||
|
{
|
||||||
|
var plane = new Plane(1, 2, 3, 4);
|
||||||
|
var vector4 = plane.AsVector4();
|
||||||
|
Assert.Equal(plane.Normal.X, vector4.X);
|
||||||
|
Assert.Equal(plane.Normal.Y, vector4.Y);
|
||||||
|
Assert.Equal(plane.Normal.Z, vector4.Z);
|
||||||
|
Assert.Equal(plane.D, vector4.W);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PlaneAsVector256Test()
|
||||||
|
{
|
||||||
|
var plane = new Plane(1, 2, 3, 4);
|
||||||
|
var vector256 = plane.AsVector256();
|
||||||
|
Assert.Equal(plane.Normal.X, vector256[0]);
|
||||||
|
Assert.Equal(plane.Normal.Y, vector256[1]);
|
||||||
|
Assert.Equal(plane.Normal.Z, vector256[2]);
|
||||||
|
Assert.Equal(plane.D, vector256[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void QuaternionAsVector4Test()
|
||||||
|
{
|
||||||
|
var quaternion = new Quaternion(1, 2, 3, 4);
|
||||||
|
var vector4 = quaternion.AsVector4();
|
||||||
|
Assert.Equal(quaternion.X, vector4.X);
|
||||||
|
Assert.Equal(quaternion.Y, vector4.Y);
|
||||||
|
Assert.Equal(quaternion.Z, vector4.Z);
|
||||||
|
Assert.Equal(quaternion.W, vector4.W);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void QuaternionAsVector256Test()
|
||||||
|
{
|
||||||
|
var quaternion = new Quaternion(1, 2, 3, 4);
|
||||||
|
var vector256 = quaternion.AsVector256();
|
||||||
|
Assert.Equal(quaternion.X, vector256[0]);
|
||||||
|
Assert.Equal(quaternion.Y, vector256[1]);
|
||||||
|
Assert.Equal(quaternion.Z, vector256[2]);
|
||||||
|
Assert.Equal(quaternion.W, vector256[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector2AsVector3Test()
|
||||||
|
{
|
||||||
|
var vector2 = new Vector2(1, 2);
|
||||||
|
var vector3 = vector2.AsVector3();
|
||||||
|
Assert.Equal(vector2.X, vector3.X);
|
||||||
|
Assert.Equal(vector2.Y, vector3.Y);
|
||||||
|
Assert.Equal(0, vector3.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector2AsVector4Test()
|
||||||
|
{
|
||||||
|
var vector2 = new Vector2(1, 2);
|
||||||
|
var vector4 = vector2.AsVector4();
|
||||||
|
Assert.Equal(vector2.X, vector4.X);
|
||||||
|
Assert.Equal(vector2.Y, vector4.Y);
|
||||||
|
Assert.Equal(0, vector4.Z);
|
||||||
|
Assert.Equal(0, vector4.W);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector2AsVector256Test()
|
||||||
|
{
|
||||||
|
var vector2 = new Vector2(1, 2);
|
||||||
|
var vector256 = vector2.AsVector256();
|
||||||
|
Assert.Equal(vector2.X, vector256[0]);
|
||||||
|
Assert.Equal(vector2.Y, vector256[1]);
|
||||||
|
Assert.Equal(0, vector256[2]);
|
||||||
|
Assert.Equal(0, vector256[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector3AsVector2Test()
|
||||||
|
{
|
||||||
|
var vector3 = new Vector3(1, 2, 3);
|
||||||
|
var vector2 = vector3.AsVector2();
|
||||||
|
Assert.Equal(vector3.X, vector2.X);
|
||||||
|
Assert.Equal(vector3.Y, vector2.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector3AsVector4Test()
|
||||||
|
{
|
||||||
|
var vector3 = new Vector3(1, 2, 3);
|
||||||
|
var vector4 = vector3.AsVector4();
|
||||||
|
Assert.Equal(vector3.X, vector4.X);
|
||||||
|
Assert.Equal(vector3.Y, vector4.Y);
|
||||||
|
Assert.Equal(vector3.Z, vector4.Z);
|
||||||
|
Assert.Equal(0, vector4.W);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector3AsVector256Test()
|
||||||
|
{
|
||||||
|
var vector3 = new Vector3(1, 2, 3);
|
||||||
|
var vector256 = vector3.AsVector256();
|
||||||
|
Assert.Equal(vector3.X, vector256[0]);
|
||||||
|
Assert.Equal(vector3.Y, vector256[1]);
|
||||||
|
Assert.Equal(vector3.Z, vector256[2]);
|
||||||
|
Assert.Equal(0, vector256[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector4AsQuaternionTest()
|
||||||
|
{
|
||||||
|
var vector4 = new Vector4(1, 2, 3, 4);
|
||||||
|
var quaternion = vector4.AsQuaternion();
|
||||||
|
Assert.Equal(vector4.X, quaternion.X);
|
||||||
|
Assert.Equal(vector4.Y, quaternion.Y);
|
||||||
|
Assert.Equal(vector4.Z, quaternion.Z);
|
||||||
|
Assert.Equal(vector4.W, quaternion.W);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector4AsPlaneTest()
|
||||||
|
{
|
||||||
|
var vector4 = new Vector4(1, 2, 3, 4);
|
||||||
|
var plane = vector4.AsPlane();
|
||||||
|
Assert.Equal(vector4.X, plane.Normal.X);
|
||||||
|
Assert.Equal(vector4.Y, plane.Normal.Y);
|
||||||
|
Assert.Equal(vector4.Z, plane.Normal.Z);
|
||||||
|
Assert.Equal(vector4.W, plane.D);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector4AsVector2Test()
|
||||||
|
{
|
||||||
|
var vector4 = new Vector4(1, 2, 3, 4);
|
||||||
|
var vector2 = vector4.AsVector2();
|
||||||
|
Assert.Equal(vector4.X, vector2.X);
|
||||||
|
Assert.Equal(vector4.Y, vector2.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector4AsVector3Test()
|
||||||
|
{
|
||||||
|
var vector4 = new Vector4(1, 2, 3, 4);
|
||||||
|
var vector3 = vector4.AsVector3();
|
||||||
|
Assert.Equal(vector4.X, vector3.X);
|
||||||
|
Assert.Equal(vector4.Y, vector3.Y);
|
||||||
|
Assert.Equal(vector4.Z, vector3.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector4AsVector256Test()
|
||||||
|
{
|
||||||
|
var vector4 = new Vector4(1, 2, 3, 4);
|
||||||
|
var vector256 = vector4.AsVector256();
|
||||||
|
Assert.Equal(vector4.X, vector256[0]);
|
||||||
|
Assert.Equal(vector4.Y, vector256[1]);
|
||||||
|
Assert.Equal(vector4.Z, vector256[2]);
|
||||||
|
Assert.Equal(vector4.W, vector256[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector256AsPlaneTest()
|
||||||
|
{
|
||||||
|
var vector256 = Vector256.Create(1d, 2d, 3d, 4d);
|
||||||
|
var plane = vector256.AsPlane();
|
||||||
|
Assert.Equal(vector256[0], plane.Normal.X);
|
||||||
|
Assert.Equal(vector256[1], plane.Normal.Y);
|
||||||
|
Assert.Equal(vector256[2], plane.Normal.Z);
|
||||||
|
Assert.Equal(vector256[3], plane.D);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector256AsQuaternionTest()
|
||||||
|
{
|
||||||
|
var vector256 = Vector256.Create(1d, 2d, 3d, 4d);
|
||||||
|
var quaternion = vector256.AsQuaternion();
|
||||||
|
Assert.Equal(vector256[0], quaternion.X);
|
||||||
|
Assert.Equal(vector256[1], quaternion.Y);
|
||||||
|
Assert.Equal(vector256[2], quaternion.Z);
|
||||||
|
Assert.Equal(vector256[3], quaternion.W);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector256AsVector2Test()
|
||||||
|
{
|
||||||
|
var vector256 = Vector256.Create(1d, 2d, 0d, 0d);
|
||||||
|
var vector2 = vector256.AsVector2();
|
||||||
|
Assert.Equal(vector256[0], vector2.X);
|
||||||
|
Assert.Equal(vector256[1], vector2.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector256AsVector3Test()
|
||||||
|
{
|
||||||
|
var vector256 = Vector256.Create(1d, 2d, 3d, 0d);
|
||||||
|
var vector3 = vector256.AsVector3();
|
||||||
|
Assert.Equal(vector256[0], vector3.X);
|
||||||
|
Assert.Equal(vector256[1], vector3.Y);
|
||||||
|
Assert.Equal(vector256[2], vector3.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector256AsVector4Test()
|
||||||
|
{
|
||||||
|
var vector256 = Vector256.Create(1d, 2d, 3d, 4d);
|
||||||
|
var vector4 = vector256.AsVector4();
|
||||||
|
Assert.Equal(vector256[0], vector4.X);
|
||||||
|
Assert.Equal(vector256[1], vector4.Y);
|
||||||
|
Assert.Equal(vector256[2], vector4.Z);
|
||||||
|
Assert.Equal(vector256[3], vector4.W);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.Text.Json;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Speckle.DoubleNumerics.Tests;
|
||||||
|
|
||||||
|
public class ConverterTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void PlaneConverterTest() => AssertRoundTrip(new Plane(1, 2, 3, 4));
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector2ConverterTest() => AssertRoundTrip(new Vector2(1, 2));
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector3ConverterTest() => AssertRoundTrip(new Vector3(1, 2, 3));
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Vector4ConverterTest() => AssertRoundTrip(new Vector4(1, 2, 3, 4));
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void QuaternionConverterTest() => AssertRoundTrip(new Quaternion(1, 2, 3, 4));
|
||||||
|
|
||||||
|
private static void AssertRoundTrip<T>(T value)
|
||||||
|
{
|
||||||
|
var json = JsonSerializer.Serialize(value);
|
||||||
|
var deserialized = JsonSerializer.Deserialize<T>(json);
|
||||||
|
Assert.Equal(value, deserialized);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.Intrinsics;
|
||||||
|
|
||||||
|
namespace Speckle.DoubleNumerics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides extension methods for converting between different numeric types.
|
||||||
|
/// </summary>
|
||||||
|
public static class ConversionExtensions
|
||||||
|
{
|
||||||
|
// TODO: When targeting .NET 8 and above, we can use the new Unsafe.BitCast method to reinterpret types.
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Plane"/> as a new <see cref="Vector4"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Plane"/> to convert.</param>
|
||||||
|
/// <returns>A <see cref="Vector4"/> representation of the <see cref="Plane"/>.</returns>
|
||||||
|
public static Vector4 AsVector4(this Plane value) => Unsafe.As<Plane, Vector4>(ref value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Plane"/> as a new <see cref="Vector256{Double}"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Plane"/> to convert.</param>
|
||||||
|
/// <returns>A <see cref="Vector256{Double}"/> representation of the <see cref="Plane"/>.</returns>
|
||||||
|
public static Vector256<double> AsVector256(this Plane value) => Unsafe.As<Plane, Vector256<double>>(ref value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Quaternion"/> as a new <see cref="Vector4"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Quaternion"/> to convert.</param>
|
||||||
|
/// <returns>A <see cref="Vector4"/> representation of the <see cref="Quaternion"/>.</returns>
|
||||||
|
public static Vector4 AsVector4(this Quaternion value) => Unsafe.As<Quaternion, Vector4>(ref value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Quaternion"/> as a new <see cref="Vector256{Double}"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Quaternion"/> to convert.</param>
|
||||||
|
/// <returns>A <see cref="Vector256{Double}"/> representation of the <see cref="Quaternion"/>.</returns>
|
||||||
|
public static Vector256<double> AsVector256(this Quaternion value) =>
|
||||||
|
Unsafe.As<Quaternion, Vector256<double>>(ref value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Vector2"/> as a new <see cref="Vector3"/> with the new element zeroed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Vector2"/> to convert.</param>
|
||||||
|
/// <returns><paramref name="value"/> reinterpreted as a new <see cref="Vector3"/> with the new element zeroed.</returns>
|
||||||
|
public static Vector3 AsVector3(this Vector2 value) => new(value, 0);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Vector2"/> as a new <see cref="Vector4"/> with the new elements zeroed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Vector2"/> to convert.</param>
|
||||||
|
/// <returns><paramref name="value"/> reinterpreted as a new <see cref="Vector4"/> with the new elements zeroed.</returns>
|
||||||
|
public static Vector4 AsVector4(this Vector2 value) => new(value, 0, 0);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Vector2"/> as a new <see cref="Vector256{Double}"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Vector2"/> to convert.</param>
|
||||||
|
/// <returns>A <see cref="Vector256{Double}"/> representation of the <see cref="Vector2"/>.</returns>
|
||||||
|
public static Vector256<double> AsVector256(this Vector2 value) => value.AsVector4().AsVector256();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Vector3"/> as a new <see cref="Vector2"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Vector3"/> to convert.</param>
|
||||||
|
/// <returns><paramref name="value"/> reinterpreted as a new <see cref="Vector2"/>.</returns>
|
||||||
|
public static Vector2 AsVector2(this Vector3 value) => value.AsVector256().AsVector2();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Vector3"/> as a new <see cref="Vector4"/> with the new element zeroed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Vector3"/> to convert.</param>
|
||||||
|
/// <returns><paramref name="value"/> reinterpreted as a new <see cref="Vector4"/> with the new element zeroed.</returns>
|
||||||
|
public static Vector4 AsVector4(this Vector3 value) => new(value, 0);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Vector3"/> as a new <see cref="Vector256{Double}"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Vector3"/> to convert.</param>
|
||||||
|
/// <returns>A <see cref="Vector256{Double}"/> representation of the <see cref="Vector3"/>.</returns>
|
||||||
|
public static Vector256<double> AsVector256(this Vector3 value) => value.AsVector4().AsVector256();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Vector4"/> as a new <see cref="Quaternion"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Vector4"/> to convert.</param>
|
||||||
|
/// <returns>A <see cref="Quaternion"/> representation of the <see cref="Vector4"/>.</returns>
|
||||||
|
public static Quaternion AsQuaternion(this Vector4 value) => Unsafe.As<Vector4, Quaternion>(ref value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Vector4"/> as a new <see cref="Plane"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Vector4"/> to convert.</param>
|
||||||
|
/// <returns>A <see cref="Plane"/> representation of the <see cref="Vector4"/>.</returns>
|
||||||
|
public static Plane AsPlane(this Vector4 value) => Unsafe.As<Vector4, Plane>(ref value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Vector4"/> as a new <see cref="Vector2"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Vector4"/> to convert.</param>
|
||||||
|
/// <returns>A <see cref="Vector2"/> representation of the <see cref="Vector4"/>.</returns>
|
||||||
|
public static Vector2 AsVector2(this Vector4 value) => value.AsVector256().AsVector2();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Vector4"/> as a new <see cref="Vector3"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Vector4"/> to convert.</param>
|
||||||
|
/// <returns>A <see cref="Vector3"/> representation of the <see cref="Vector4"/>.</returns>
|
||||||
|
public static Vector3 AsVector3(this Vector4 value) => value.AsVector256().AsVector3();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Vector4"/> as a new <see cref="Vector256{Double}"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Vector4"/> to convert.</param>
|
||||||
|
/// <returns>A <see cref="Vector256{Double}"/> representation of the <see cref="Vector4"/>.</returns>
|
||||||
|
public static Vector256<double> AsVector256(this Vector4 value) => Unsafe.As<Vector4, Vector256<double>>(ref value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Vector256{Double}"/> as a new <see cref="Plane"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Vector256{Double}"/> to convert.</param>
|
||||||
|
/// <returns>A <see cref="Plane"/> representation of the <see cref="Vector256{Double}"/>.</returns>
|
||||||
|
public static Plane AsPlane(this Vector256<double> value) => Unsafe.As<Vector256<double>, Plane>(ref value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Vector256{Double}"/> as a new <see cref="Quaternion"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Vector256{Double}"/> to convert.</param>
|
||||||
|
/// <returns>A <see cref="Quaternion"/> representation of the <see cref="Vector256{Double}"/>.</returns>
|
||||||
|
public static Quaternion AsQuaternion(this Vector256<double> value) =>
|
||||||
|
Unsafe.As<Vector256<double>, Quaternion>(ref value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Vector256{Double}"/> as a new <see cref="Vector2"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Vector256{Double}"/> to convert.</param>
|
||||||
|
/// <returns>A <see cref="Vector2"/> representation of the <see cref="Vector256{Double}"/>.</returns>
|
||||||
|
public static Vector2 AsVector2(this Vector256<double> value)
|
||||||
|
{
|
||||||
|
ref byte address = ref Unsafe.As<Vector256<double>, byte>(ref value);
|
||||||
|
return Unsafe.ReadUnaligned<Vector2>(ref address);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Vector256{Double}"/> as a new <see cref="Vector3"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Vector256{Double}"/> to convert.</param>
|
||||||
|
/// <returns>A <see cref="Vector3"/> representation of the <see cref="Vector256{Double}"/>.</returns>
|
||||||
|
public static Vector3 AsVector3(this Vector256<double> value)
|
||||||
|
{
|
||||||
|
ref byte address = ref Unsafe.As<Vector256<double>, byte>(ref value);
|
||||||
|
return Unsafe.ReadUnaligned<Vector3>(ref address);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reinterprets a <see cref="Vector256{Double}"/> as a new <see cref="Vector4"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The <see cref="Vector256{Double}"/> to convert.</param>
|
||||||
|
/// <returns>A <see cref="Vector4"/> representation of the <see cref="Vector256{Double}"/>.</returns>
|
||||||
|
public static Vector4 AsVector4(this Vector256<double> value) => Unsafe.As<Vector256<double>, Vector4>(ref value);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -10,7 +10,7 @@ namespace Speckle.DoubleNumerics;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A structure encapsulating a 3D Plane
|
/// A structure encapsulating a 3D Plane
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public struct Plane : IEquatable<Plane>
|
public partial struct Plane : IEquatable<Plane>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The normal vector of the Plane.
|
/// The normal vector of the Plane.
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Speckle.DoubleNumerics;
|
||||||
|
|
||||||
|
[JsonConverter(typeof(PlaneJsonConverter))]
|
||||||
|
public partial struct Plane;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converter for <see cref="Plane"/> to and from JSON.
|
||||||
|
/// </summary>
|
||||||
|
public class PlaneJsonConverter : JsonConverter<Plane>
|
||||||
|
{
|
||||||
|
public override Plane Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (reader.TokenType != JsonTokenType.StartObject)
|
||||||
|
{
|
||||||
|
throw new JsonException();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 normal = default;
|
||||||
|
double d = 0;
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.EndObject)
|
||||||
|
{
|
||||||
|
return new Plane(normal, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.TokenType != JsonTokenType.PropertyName)
|
||||||
|
{
|
||||||
|
throw new JsonException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var propertyName = reader.GetString();
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
|
||||||
|
var comparison = options.PropertyNameCaseInsensitive
|
||||||
|
? StringComparison.OrdinalIgnoreCase
|
||||||
|
: StringComparison.Ordinal;
|
||||||
|
|
||||||
|
if (string.Equals(propertyName, nameof(Plane.Normal), comparison))
|
||||||
|
{
|
||||||
|
var vectorConverter = (JsonConverter<Vector3>)options.GetConverter(typeof(Vector3));
|
||||||
|
normal = vectorConverter.Read(ref reader, typeof(Vector3), options);
|
||||||
|
}
|
||||||
|
else if (string.Equals(propertyName, nameof(Plane.D), comparison))
|
||||||
|
{
|
||||||
|
d = reader.GetDouble();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader.Skip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new JsonException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, Plane value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteStartObject();
|
||||||
|
writer.WritePropertyName(ConvertName(nameof(value.Normal), options));
|
||||||
|
var vectorConverter = (JsonConverter<Vector3>)options.GetConverter(typeof(Vector3));
|
||||||
|
vectorConverter.Write(writer, value.Normal, options);
|
||||||
|
writer.WriteNumber(ConvertName(nameof(value.D), options), value.D);
|
||||||
|
writer.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ConvertName(string name, JsonSerializerOptions options) =>
|
||||||
|
options.PropertyNamingPolicy?.ConvertName(name) ?? name;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -10,7 +10,7 @@ namespace Speckle.DoubleNumerics;
|
|||||||
/// A structure encapsulating a four-dimensional vector (x,y,z,w),
|
/// A structure encapsulating a four-dimensional vector (x,y,z,w),
|
||||||
/// which is used to efficiently rotate an object about the (x,y,z) vector by the angle theta, where w = cos(theta/2).
|
/// which is used to efficiently rotate an object about the (x,y,z) vector by the angle theta, where w = cos(theta/2).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public struct Quaternion : IEquatable<Quaternion>
|
public partial struct Quaternion : IEquatable<Quaternion>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the X-value of the vector component of the Quaternion.
|
/// Specifies the X-value of the vector component of the Quaternion.
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Speckle.DoubleNumerics;
|
||||||
|
|
||||||
|
[JsonConverter(typeof(QuaternionJsonConverter))]
|
||||||
|
public partial struct Quaternion;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converter for <see cref="Quaternion"/> to and from JSON.
|
||||||
|
/// </summary>
|
||||||
|
public class QuaternionJsonConverter : JsonConverter<Quaternion>
|
||||||
|
{
|
||||||
|
public override Quaternion Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (reader.TokenType != JsonTokenType.StartObject)
|
||||||
|
{
|
||||||
|
throw new JsonException();
|
||||||
|
}
|
||||||
|
|
||||||
|
double x = 0;
|
||||||
|
double y = 0;
|
||||||
|
double z = 0;
|
||||||
|
double w = 0;
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.EndObject)
|
||||||
|
{
|
||||||
|
return new Quaternion(x, y, z, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.TokenType != JsonTokenType.PropertyName)
|
||||||
|
{
|
||||||
|
throw new JsonException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var propertyName = reader.GetString();
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
|
||||||
|
var comparison = options.PropertyNameCaseInsensitive
|
||||||
|
? StringComparison.OrdinalIgnoreCase
|
||||||
|
: StringComparison.Ordinal;
|
||||||
|
|
||||||
|
if (string.Equals(propertyName, nameof(Quaternion.X), comparison))
|
||||||
|
{
|
||||||
|
x = reader.GetDouble();
|
||||||
|
}
|
||||||
|
else if (string.Equals(propertyName, nameof(Quaternion.Y), comparison))
|
||||||
|
{
|
||||||
|
y = reader.GetDouble();
|
||||||
|
}
|
||||||
|
else if (string.Equals(propertyName, nameof(Quaternion.Z), comparison))
|
||||||
|
{
|
||||||
|
z = reader.GetDouble();
|
||||||
|
}
|
||||||
|
else if (string.Equals(propertyName, nameof(Quaternion.W), comparison))
|
||||||
|
{
|
||||||
|
w = reader.GetDouble();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader.Skip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new JsonException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, Quaternion value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteStartObject();
|
||||||
|
writer.WriteNumber(ConvertName(nameof(value.X), options), value.X);
|
||||||
|
writer.WriteNumber(ConvertName(nameof(value.Y), options), value.Y);
|
||||||
|
writer.WriteNumber(ConvertName(nameof(value.Z), options), value.Z);
|
||||||
|
writer.WriteNumber(ConvertName(nameof(value.W), options), value.W);
|
||||||
|
writer.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ConvertName(string name, JsonSerializerOptions options) =>
|
||||||
|
options.PropertyNamingPolicy?.ConvertName(name) ?? name;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Speckle.DoubleNumerics;
|
||||||
|
|
||||||
|
[JsonConverter(typeof(Vector2JsonConverter))]
|
||||||
|
public partial struct Vector2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converter for <see cref="Vector2"/> to and from JSON.
|
||||||
|
/// </summary>
|
||||||
|
public class Vector2JsonConverter : JsonConverter<Vector2>
|
||||||
|
{
|
||||||
|
public override Vector2 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (reader.TokenType != JsonTokenType.StartObject)
|
||||||
|
{
|
||||||
|
throw new JsonException();
|
||||||
|
}
|
||||||
|
|
||||||
|
double x = 0;
|
||||||
|
double y = 0;
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.EndObject)
|
||||||
|
{
|
||||||
|
return new Vector2(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.TokenType != JsonTokenType.PropertyName)
|
||||||
|
{
|
||||||
|
throw new JsonException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var propertyName = reader.GetString();
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
|
||||||
|
var comparison = options.PropertyNameCaseInsensitive
|
||||||
|
? StringComparison.OrdinalIgnoreCase
|
||||||
|
: StringComparison.Ordinal;
|
||||||
|
|
||||||
|
if (string.Equals(propertyName, nameof(Vector2.X), comparison))
|
||||||
|
{
|
||||||
|
x = reader.GetDouble();
|
||||||
|
}
|
||||||
|
else if (string.Equals(propertyName, nameof(Vector2.Y), comparison))
|
||||||
|
{
|
||||||
|
y = reader.GetDouble();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader.Skip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new JsonException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, Vector2 value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteStartObject();
|
||||||
|
writer.WriteNumber(ConvertName(nameof(value.X), options), value.X);
|
||||||
|
writer.WriteNumber(ConvertName(nameof(value.Y), options), value.Y);
|
||||||
|
writer.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ConvertName(string name, JsonSerializerOptions options) =>
|
||||||
|
options.PropertyNamingPolicy?.ConvertName(name) ?? name;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Speckle.DoubleNumerics;
|
||||||
|
|
||||||
|
[JsonConverter(typeof(Vector3JsonConverter))]
|
||||||
|
public partial struct Vector3;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converter for <see cref="Vector3"/> to and from JSON.
|
||||||
|
/// </summary>
|
||||||
|
public class Vector3JsonConverter : JsonConverter<Vector3>
|
||||||
|
{
|
||||||
|
public override Vector3 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (reader.TokenType != JsonTokenType.StartObject)
|
||||||
|
{
|
||||||
|
throw new JsonException();
|
||||||
|
}
|
||||||
|
|
||||||
|
double x = 0;
|
||||||
|
double y = 0;
|
||||||
|
double z = 0;
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.EndObject)
|
||||||
|
{
|
||||||
|
return new Vector3(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.TokenType != JsonTokenType.PropertyName)
|
||||||
|
{
|
||||||
|
throw new JsonException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var propertyName = reader.GetString();
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
|
||||||
|
var comparison = options.PropertyNameCaseInsensitive
|
||||||
|
? StringComparison.OrdinalIgnoreCase
|
||||||
|
: StringComparison.Ordinal;
|
||||||
|
|
||||||
|
if (string.Equals(propertyName, nameof(Vector3.X), comparison))
|
||||||
|
{
|
||||||
|
x = reader.GetDouble();
|
||||||
|
}
|
||||||
|
else if (string.Equals(propertyName, nameof(Vector3.Y), comparison))
|
||||||
|
{
|
||||||
|
y = reader.GetDouble();
|
||||||
|
}
|
||||||
|
else if (string.Equals(propertyName, nameof(Vector3.Z), comparison))
|
||||||
|
{
|
||||||
|
z = reader.GetDouble();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader.Skip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new JsonException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, Vector3 value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteStartObject();
|
||||||
|
writer.WriteNumber(ConvertName(nameof(value.X), options), value.X);
|
||||||
|
writer.WriteNumber(ConvertName(nameof(value.Y), options), value.Y);
|
||||||
|
writer.WriteNumber(ConvertName(nameof(value.Z), options), value.Z);
|
||||||
|
writer.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ConvertName(string name, JsonSerializerOptions options) =>
|
||||||
|
options.PropertyNamingPolicy?.ConvertName(name) ?? name;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Speckle.DoubleNumerics;
|
||||||
|
|
||||||
|
[JsonConverter(typeof(Vector4JsonConverter))]
|
||||||
|
public partial struct Vector4;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converter for <see cref="Vector4"/> to and from JSON.
|
||||||
|
/// </summary>
|
||||||
|
public class Vector4JsonConverter : JsonConverter<Vector4>
|
||||||
|
{
|
||||||
|
public override Vector4 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (reader.TokenType != JsonTokenType.StartObject)
|
||||||
|
{
|
||||||
|
throw new JsonException();
|
||||||
|
}
|
||||||
|
|
||||||
|
double x = 0;
|
||||||
|
double y = 0;
|
||||||
|
double z = 0;
|
||||||
|
double w = 0;
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.EndObject)
|
||||||
|
{
|
||||||
|
return new Vector4(x, y, z, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.TokenType != JsonTokenType.PropertyName)
|
||||||
|
{
|
||||||
|
throw new JsonException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var propertyName = reader.GetString();
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
|
||||||
|
var comparison = options.PropertyNameCaseInsensitive
|
||||||
|
? StringComparison.OrdinalIgnoreCase
|
||||||
|
: StringComparison.Ordinal;
|
||||||
|
|
||||||
|
if (string.Equals(propertyName, nameof(Vector4.X), comparison))
|
||||||
|
{
|
||||||
|
x = reader.GetDouble();
|
||||||
|
}
|
||||||
|
else if (string.Equals(propertyName, nameof(Vector4.Y), comparison))
|
||||||
|
{
|
||||||
|
y = reader.GetDouble();
|
||||||
|
}
|
||||||
|
else if (string.Equals(propertyName, nameof(Vector4.Z), comparison))
|
||||||
|
{
|
||||||
|
z = reader.GetDouble();
|
||||||
|
}
|
||||||
|
else if (string.Equals(propertyName, nameof(Vector4.W), comparison))
|
||||||
|
{
|
||||||
|
w = reader.GetDouble();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader.Skip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new JsonException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, Vector4 value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteStartObject();
|
||||||
|
writer.WriteNumber(ConvertName(nameof(value.X), options), value.X);
|
||||||
|
writer.WriteNumber(ConvertName(nameof(value.Y), options), value.Y);
|
||||||
|
writer.WriteNumber(ConvertName(nameof(value.Z), options), value.Z);
|
||||||
|
writer.WriteNumber(ConvertName(nameof(value.W), options), value.W);
|
||||||
|
writer.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ConvertName(string name, JsonSerializerOptions options) =>
|
||||||
|
options.PropertyNamingPolicy?.ConvertName(name) ?? name;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user