Compare commits
No commits in common. "791fda6a7f00c3e6b5ca3de5fcdc3a053a4da6ab" and "75e5c02609b194d2b92a6e25a493e5857f193873" have entirely different histories.
791fda6a7f
...
75e5c02609
50 changed files with 2862 additions and 3991 deletions
|
|
@ -1,10 +1,26 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 1 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public enum AngleUnit
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
namespace BGC
|
||||
{
|
||||
public enum Attitude
|
||||
{
|
||||
ANY = 0,
|
||||
ZERO = 1,
|
||||
ORTHOGONAL = 2,
|
||||
CO_DIRECTIONAL = 3,
|
||||
COUNTER_DIRECTIONAL = 4
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
namespace BGC
|
||||
{
|
||||
public enum Axis
|
||||
{
|
||||
X1 = 1,
|
||||
X2 = 2,
|
||||
X3 = 3,
|
||||
REVERSE_X1 = -1,
|
||||
REVERSE_X2 = -2,
|
||||
REVERSE_X3 = -3
|
||||
}
|
||||
}
|
||||
|
|
@ -1,171 +0,0 @@
|
|||
|
||||
namespace BGC
|
||||
{
|
||||
public struct ComplexFP32
|
||||
{
|
||||
public float real = 0.0f;
|
||||
public float imaginary = 0.0f;
|
||||
|
||||
public ComplexFP32(float real, float imaginary)
|
||||
{
|
||||
this.real = real;
|
||||
this.imaginary = imaginary;
|
||||
}
|
||||
|
||||
public ComplexFP32(in ComplexFP32 number)
|
||||
{
|
||||
this.real = number.real;
|
||||
this.imaginary = number.imaginary;
|
||||
}
|
||||
|
||||
public readonly float GetSquareModulus()
|
||||
{
|
||||
return this.real * this.real + this.imaginary * this.imaginary;
|
||||
}
|
||||
|
||||
public readonly float GetModulus()
|
||||
{
|
||||
return MathF.Sqrt(GetSquareModulus());
|
||||
}
|
||||
|
||||
public readonly bool IsZero()
|
||||
{
|
||||
return GetSquareModulus() <= UtilityFP32.SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
public readonly bool IsUnit()
|
||||
{
|
||||
return UtilityFP32.IsSqareUnit(GetSquareModulus());
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.real = 0.0f;
|
||||
this.imaginary = 0.0f;
|
||||
}
|
||||
|
||||
public void MakeOpposite()
|
||||
{
|
||||
this.real = -this.real;
|
||||
this.imaginary = -this.imaginary;
|
||||
}
|
||||
|
||||
public bool Normalize()
|
||||
{
|
||||
float squareModulus = this.GetSquareModulus();
|
||||
|
||||
if (UtilityFP32.IsSqareUnit(squareModulus))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON || float.IsNaN(squareModulus))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float multiplier = MathF.Sqrt(1.0f / squareModulus);
|
||||
|
||||
this.real *= multiplier;
|
||||
this.imaginary *= multiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Conjugate()
|
||||
{
|
||||
this.imaginary = -this.imaginary;
|
||||
}
|
||||
|
||||
public bool Invert()
|
||||
{
|
||||
float squareModulus = this.GetSquareModulus();
|
||||
|
||||
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON || float.IsNaN(squareModulus))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float multiplicand = 1.0f / squareModulus;
|
||||
|
||||
this.real *= multiplicand;
|
||||
this.imaginary = -this.imaginary * multiplicand;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetValues(float real, float imaginary)
|
||||
{
|
||||
this.real = real;
|
||||
this.imaginary = imaginary;
|
||||
}
|
||||
|
||||
public void SetValues(in ComplexFP32 number)
|
||||
{
|
||||
this.real = number.real;
|
||||
this.imaginary = number.imaginary;
|
||||
}
|
||||
|
||||
public static void Reset(out ComplexFP32 number)
|
||||
{
|
||||
number.real = 0.0f;
|
||||
number.imaginary = 0.0f;
|
||||
}
|
||||
|
||||
public static void GetOpposite(in ComplexFP32 number, out ComplexFP32 opposite)
|
||||
{
|
||||
opposite.real = -number.real;
|
||||
opposite.imaginary = -number.imaginary;
|
||||
}
|
||||
|
||||
public static bool GetNormalized(in ComplexFP32 number, out ComplexFP32 normalized)
|
||||
{
|
||||
float squareModulus = number.GetSquareModulus();
|
||||
|
||||
if (UtilityFP64.IsSqareUnit(squareModulus))
|
||||
{
|
||||
normalized.real = number.real;
|
||||
normalized.imaginary = number.imaginary;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (squareModulus <= UtilityFP64.SQUARE_EPSYLON || float.IsNaN(squareModulus))
|
||||
{
|
||||
normalized.real = 0.0f;
|
||||
normalized.imaginary = 0.0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
float multiplier = MathF.Sqrt(1.0f / squareModulus);
|
||||
|
||||
normalized.real = number.real * multiplier;
|
||||
normalized.imaginary = number.imaginary * multiplier;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void GetConjugate(in ComplexFP32 number, out ComplexFP32 conjugate)
|
||||
{
|
||||
conjugate.real = number.real;
|
||||
conjugate.imaginary = -number.imaginary;
|
||||
}
|
||||
|
||||
public static bool GetInverse(in ComplexFP32 number, out ComplexFP32 inverse)
|
||||
{
|
||||
float squareModulus = number.GetSquareModulus();
|
||||
|
||||
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON || float.IsNaN(squareModulus))
|
||||
{
|
||||
inverse.real = 0.0f;
|
||||
inverse.imaginary = 0.0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
float multiplicand = 1.0f / squareModulus;
|
||||
|
||||
inverse.real = number.real * multiplicand;
|
||||
inverse.imaginary = -number.imaginary * multiplicand;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +1,40 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 1 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public static class AngleFP32
|
||||
public static class FP32Angle
|
||||
{
|
||||
public static float ToRadians(float angle, AngleUnit unit)
|
||||
{
|
||||
if (unit == AngleUnit.DEGREES)
|
||||
{
|
||||
return angle * DegreeFP32.RADIANS_IN_DEGREE;
|
||||
return angle * FP32Degrees.RADIANS_IN_DEGREE;
|
||||
}
|
||||
|
||||
if (unit == AngleUnit.TURNS)
|
||||
{
|
||||
return angle * RadianFP32.TWO_PI;
|
||||
return angle * FP32Radians.TWO_PI;
|
||||
}
|
||||
|
||||
return angle;
|
||||
|
|
@ -27,7 +44,7 @@ namespace BGC
|
|||
{
|
||||
if (unit == AngleUnit.RADIANS)
|
||||
{
|
||||
return angle * RadianFP32.DEGREES_IN_RADIAN;
|
||||
return angle * FP32Radians.DEGREES_IN_RADIAN;
|
||||
}
|
||||
|
||||
if (unit == AngleUnit.TURNS)
|
||||
|
|
@ -42,12 +59,12 @@ namespace BGC
|
|||
{
|
||||
if (unit == AngleUnit.RADIANS)
|
||||
{
|
||||
return angle * RadianFP32.TURNS_IN_RADIAN;
|
||||
return angle * FP32Radians.TURNS_IN_RADIAN;
|
||||
}
|
||||
|
||||
if (unit == AngleUnit.DEGREES)
|
||||
{
|
||||
return angle * DegreeFP32.TURNS_IN_DEGREE;
|
||||
return angle * FP32Degrees.TURNS_IN_DEGREE;
|
||||
}
|
||||
|
||||
return angle;
|
||||
|
|
@ -65,7 +82,7 @@ namespace BGC
|
|||
return 1.0f;
|
||||
}
|
||||
|
||||
return RadianFP32.TWO_PI;
|
||||
return FP32Radians.TWO_PI;
|
||||
}
|
||||
|
||||
public static float GetHalfCircle(AngleUnit unit)
|
||||
|
|
@ -80,7 +97,7 @@ namespace BGC
|
|||
return 0.5f;
|
||||
}
|
||||
|
||||
return RadianFP32.PI;
|
||||
return FP32Radians.PI;
|
||||
}
|
||||
|
||||
public static float GetQuarterCircle(AngleUnit unit)
|
||||
|
|
@ -95,22 +112,22 @@ namespace BGC
|
|||
return 0.25f;
|
||||
}
|
||||
|
||||
return RadianFP32.HALF_OF_PI;
|
||||
return FP32Radians.HALF_OF_PI;
|
||||
}
|
||||
|
||||
public static float Normalize(float angle, AngleUnit unit, AngleRange range)
|
||||
{
|
||||
if (unit == AngleUnit.DEGREES)
|
||||
{
|
||||
return DegreeFP32.Normalize(angle, range);
|
||||
return FP32Degrees.Normalize(angle, range);
|
||||
}
|
||||
|
||||
if (unit == AngleUnit.TURNS)
|
||||
{
|
||||
return TurnFP32.Normalize(angle, range);
|
||||
return FP32Turns.Normalize(angle, range);
|
||||
}
|
||||
|
||||
return RadianFP32.Normalize(angle, range);
|
||||
return FP32Radians.Normalize(angle, range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 18 Nov 2024
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public class DegreeFP32
|
||||
public class FP32Degrees
|
||||
{
|
||||
public const float RADIANS_IN_DEGREE = 1.745329252E-2f;
|
||||
public const float TURNS_IN_DEGREE = 2.7777777778E-3f;
|
||||
|
|
@ -1,23 +1,40 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 10 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public struct Matrix2x2FP32
|
||||
public struct FP32Matrix2x2
|
||||
{
|
||||
public float r1c1 = 0.0f, r1c2 = 0.0f;
|
||||
public float r2c1 = 0.0f, r2c2 = 0.0f;
|
||||
|
||||
public Matrix2x2FP32(float d1, float d2)
|
||||
public FP32Matrix2x2(float d1, float d2)
|
||||
{
|
||||
this.r1c1 = d1;
|
||||
this.r2c2 = d2;
|
||||
}
|
||||
|
||||
public Matrix2x2FP32(in Matrix2x2FP32 matrix)
|
||||
public FP32Matrix2x2(in FP32Matrix2x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -26,7 +43,7 @@ namespace BGC
|
|||
this.r2c2 = matrix.r2c2;
|
||||
}
|
||||
|
||||
public Matrix2x2FP32(in Matrix2x2FP64 matrix)
|
||||
public FP32Matrix2x2(in FP64Matrix2x2 matrix)
|
||||
{
|
||||
this.r1c1 = (float)matrix.r1c1;
|
||||
this.r1c2 = (float)matrix.r1c2;
|
||||
|
|
@ -42,7 +59,8 @@ namespace BGC
|
|||
|
||||
public readonly bool IsSingular()
|
||||
{
|
||||
return UtilityFP32.IsZero(this.GetDeterminant());
|
||||
float determinant = this.GetDeterminant();
|
||||
return -FP32Utility.EPSYLON <= determinant && determinant <= FP32Utility.EPSYLON;
|
||||
}
|
||||
|
||||
public void Transpose()
|
||||
|
|
@ -54,7 +72,7 @@ namespace BGC
|
|||
{
|
||||
float determinant = this.GetDeterminant();
|
||||
|
||||
if (UtilityFP32.IsZero(determinant))
|
||||
if (-FP32Utility.EPSYLON <= determinant && determinant <= FP32Utility.EPSYLON)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -103,7 +121,7 @@ namespace BGC
|
|||
this.r2c2 = d2;
|
||||
}
|
||||
|
||||
public void Set(in Matrix2x2FP32 matrix)
|
||||
public void SetValues(in FP32Matrix2x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -112,7 +130,7 @@ namespace BGC
|
|||
this.r2c2 = matrix.r2c2;
|
||||
}
|
||||
|
||||
public void Set(in Matrix2x2FP64 matrix)
|
||||
public void SetValues(in FP64Matrix2x2 matrix)
|
||||
{
|
||||
this.r1c1 = (float)matrix.r1c1;
|
||||
this.r1c2 = (float)matrix.r1c2;
|
||||
|
|
@ -121,14 +139,14 @@ namespace BGC
|
|||
this.r2c2 = (float)matrix.r2c2;
|
||||
}
|
||||
|
||||
public void SetTransposedOf(in Matrix2x2FP32 matrix)
|
||||
public void SetTransposedOf(in FP32Matrix2x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r2c2 = matrix.r2c2;
|
||||
(this.r1c2, this.r2c1) = (matrix.r2c1, matrix.r1c2);
|
||||
}
|
||||
|
||||
public void SetTransposedOf(in Matrix2x2FP64 matrix)
|
||||
public void SetTransposedOf(in FP64Matrix2x2 matrix)
|
||||
{
|
||||
this.r1c1 = (float)matrix.r1c1;
|
||||
this.r1c2 = (float)matrix.r2c1;
|
||||
|
|
@ -137,11 +155,11 @@ namespace BGC
|
|||
this.r2c2 = (float)matrix.r2c2;
|
||||
}
|
||||
|
||||
public bool SetInvertedOf(in Matrix2x2FP32 matrix)
|
||||
public bool SetInvertedOf(in FP32Matrix2x2 matrix)
|
||||
{
|
||||
float determinant = matrix.GetDeterminant();
|
||||
|
||||
if (-UtilityFP32.EPSYLON <= determinant && determinant <= UtilityFP32.EPSYLON)
|
||||
if (-FP32Utility.EPSYLON <= determinant && determinant <= FP32Utility.EPSYLON)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -187,7 +205,7 @@ namespace BGC
|
|||
this.r2c2 = r2;
|
||||
}
|
||||
|
||||
public void AppendScaled(in Matrix2x2FP32 matrix, float scale)
|
||||
public void AppendScaled(in FP32Matrix2x2 matrix, float scale)
|
||||
{
|
||||
this.r1c1 += matrix.r1c1 * scale;
|
||||
this.r1c2 += matrix.r1c2 * scale;
|
||||
|
|
@ -196,7 +214,7 @@ namespace BGC
|
|||
this.r2c2 += matrix.r2c2 * scale;
|
||||
}
|
||||
|
||||
public static void Add(in Matrix2x2FP32 matrix1, in Matrix2x2FP32 matrix2, out Matrix2x2FP32 result)
|
||||
public static void Add(in FP32Matrix2x2 matrix1, in FP32Matrix2x2 matrix2, out FP32Matrix2x2 result)
|
||||
{
|
||||
result.r1c1 = matrix1.r1c1 + matrix2.r1c1;
|
||||
result.r1c2 = matrix1.r1c2 + matrix2.r1c2;
|
||||
|
|
@ -205,7 +223,7 @@ namespace BGC
|
|||
result.r2c2 = matrix1.r2c2 + matrix2.r2c2;
|
||||
}
|
||||
|
||||
public static void Subtract(in Matrix2x2FP32 minuend, in Matrix2x2FP32 subtrahend, out Matrix2x2FP32 difference)
|
||||
public static void Subtract(in FP32Matrix2x2 minuend, in FP32Matrix2x2 subtrahend, out FP32Matrix2x2 difference)
|
||||
{
|
||||
difference.r1c1 = minuend.r1c1 - subtrahend.r1c1;
|
||||
difference.r1c2 = minuend.r1c2 - subtrahend.r1c2;
|
||||
|
|
@ -214,7 +232,7 @@ namespace BGC
|
|||
difference.r2c2 = minuend.r2c2 - subtrahend.r2c2;
|
||||
}
|
||||
|
||||
public static void Multiply(in Matrix2x2FP32 multiplicand, float multiplier, out Matrix2x2FP32 product)
|
||||
public static void Multiply(in FP32Matrix2x2 multiplicand, float multiplier, out FP32Matrix2x2 product)
|
||||
{
|
||||
product.r1c1 = multiplicand.r1c1 * multiplier;
|
||||
product.r1c2 = multiplicand.r1c2 * multiplier;
|
||||
|
|
@ -223,12 +241,12 @@ namespace BGC
|
|||
product.r2c2 = multiplicand.r2c2 * multiplier;
|
||||
}
|
||||
|
||||
public static void Divide(in Matrix2x2FP32 dividend, float divisor, out Matrix2x2FP32 quotient)
|
||||
public static void Divide(in FP32Matrix2x2 dividend, float divisor, out FP32Matrix2x2 quotient)
|
||||
{
|
||||
Multiply(dividend, 1.0f / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void GetRightProduct(in Matrix2x2FP32 matrix, in Vector2FP32 vector, out Vector2FP32 result)
|
||||
public static void GetRightProduct(in FP32Matrix2x2 matrix, in FP32Vector2 vector, out FP32Vector2 result)
|
||||
{
|
||||
float x1 = matrix.r1c1 * vector.x1 + matrix.r1c2 * vector.x2;
|
||||
float x2 = matrix.r2c1 * vector.x1 + matrix.r2c2 * vector.x2;
|
||||
|
|
@ -237,7 +255,7 @@ namespace BGC
|
|||
result.x2 = x2;
|
||||
}
|
||||
|
||||
public static void GetLeftProduct(in Vector2FP32 vector, in Matrix2x2FP32 matrix, out Vector2FP32 result)
|
||||
public static void GetLeftProduct(in FP32Vector2 vector, in FP32Matrix2x2 matrix, out FP32Vector2 result)
|
||||
{
|
||||
float x1 = vector.x1 * matrix.r1c1 + vector.x2 * matrix.r2c1;
|
||||
float x2 = vector.x1 * matrix.r1c2 + vector.x2 * matrix.r2c2;
|
||||
|
|
@ -246,7 +264,7 @@ namespace BGC
|
|||
result.x2 = x2;
|
||||
}
|
||||
|
||||
public static void LoadZero(out Matrix2x2FP32 matrix)
|
||||
public static void LoadZero(out FP32Matrix2x2 matrix)
|
||||
{
|
||||
matrix.r1c1 = 0.0f;
|
||||
matrix.r1c2 = 0.0f;
|
||||
|
|
@ -255,7 +273,7 @@ namespace BGC
|
|||
matrix.r2c2 = 0.0f;
|
||||
}
|
||||
|
||||
public static void LoadIdentity(out Matrix2x2FP32 matrix)
|
||||
public static void LoadIdentity(out FP32Matrix2x2 matrix)
|
||||
{
|
||||
matrix.r1c1 = 1.0f;
|
||||
matrix.r1c2 = 0.0f;
|
||||
|
|
@ -264,7 +282,7 @@ namespace BGC
|
|||
matrix.r2c2 = 1.0f;
|
||||
}
|
||||
|
||||
public static void LoadDiagonal(float d1, float d2, out Matrix2x2FP32 matrix)
|
||||
public static void LoadDiagonal(float d1, float d2, out FP32Matrix2x2 matrix)
|
||||
{
|
||||
matrix.r1c1 = d1;
|
||||
matrix.r1c2 = 0.0f;
|
||||
|
|
@ -1,17 +1,34 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 11 Nov 2024
|
||||
*/
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public struct Matrix2x3FP32
|
||||
public struct FP32Matrix2x3
|
||||
{
|
||||
public float r1c1 = 0.0f, r1c2 = 0.0f;
|
||||
public float r2c1 = 0.0f, r2c2 = 0.0f;
|
||||
public float r3c1 = 0.0f, r3c2 = 0.0f;
|
||||
|
||||
public Matrix2x3FP32(in Matrix2x3FP32 matrix)
|
||||
public FP32Matrix2x3(in FP32Matrix2x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -23,7 +40,7 @@ namespace BGC
|
|||
this.r3c2 = matrix.r3c2;
|
||||
}
|
||||
|
||||
public Matrix2x3FP32(in Matrix2x3FP64 matrix)
|
||||
public FP32Matrix2x3(in FP64Matrix2x3 matrix)
|
||||
{
|
||||
this.r1c1 = (float) matrix.r1c1;
|
||||
this.r1c2 = (float) matrix.r1c2;
|
||||
|
|
@ -35,7 +52,7 @@ namespace BGC
|
|||
this.r3c2 = (float) matrix.r3c2;
|
||||
}
|
||||
|
||||
public Matrix2x3FP32(in Matrix3x2FP32 matrix)
|
||||
public FP32Matrix2x3(in FP32Matrix3x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r2c1;
|
||||
|
|
@ -47,7 +64,7 @@ namespace BGC
|
|||
this.r3c2 = matrix.r2c3;
|
||||
}
|
||||
|
||||
public Matrix2x3FP32(in Matrix3x2FP64 matrix)
|
||||
public FP32Matrix2x3(in FP64Matrix3x2 matrix)
|
||||
{
|
||||
this.r1c1 = (float) matrix.r1c1;
|
||||
this.r1c2 = (float) matrix.r2c1;
|
||||
|
|
@ -71,7 +88,7 @@ namespace BGC
|
|||
this.r3c2 = 0.0f;
|
||||
}
|
||||
|
||||
public void SetValues(in Matrix2x3FP32 matrix)
|
||||
public void SetValues(in FP32Matrix2x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -83,7 +100,7 @@ namespace BGC
|
|||
this.r3c2 = matrix.r3c2;
|
||||
}
|
||||
|
||||
public void SetValues(in Matrix2x3FP64 matrix)
|
||||
public void SetValues(in FP64Matrix2x3 matrix)
|
||||
{
|
||||
this.r1c1 = (float) matrix.r1c1;
|
||||
this.r1c2 = (float) matrix.r1c2;
|
||||
|
|
@ -95,7 +112,7 @@ namespace BGC
|
|||
this.r3c2 = (float) matrix.r3c2;
|
||||
}
|
||||
|
||||
public void SetTransposed(in Matrix3x2FP32 matrix)
|
||||
public void SetTransposed(in FP32Matrix3x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r2c1;
|
||||
|
|
@ -107,7 +124,7 @@ namespace BGC
|
|||
this.r3c2 = matrix.r2c3;
|
||||
}
|
||||
|
||||
public void SetTransposed(in Matrix3x2FP64 matrix)
|
||||
public void SetTransposed(in FP64Matrix3x2 matrix)
|
||||
{
|
||||
this.r1c1 = (float) matrix.r1c1;
|
||||
this.r1c2 = (float) matrix.r2c1;
|
||||
|
|
@ -151,7 +168,7 @@ namespace BGC
|
|||
this.r3c2 = r3;
|
||||
}
|
||||
|
||||
public void AppendScaled(in Matrix2x3FP32 matrix, float scale)
|
||||
public void AppendScaled(in FP32Matrix2x3 matrix, float scale)
|
||||
{
|
||||
this.r1c1 += matrix.r1c1 * scale;
|
||||
this.r1c2 += matrix.r1c2 * scale;
|
||||
|
|
@ -163,7 +180,7 @@ namespace BGC
|
|||
this.r3c2 += matrix.r3c2 * scale;
|
||||
}
|
||||
|
||||
public static void Add(in Matrix2x3FP32 matrix1, in Matrix2x3FP32 matrix2, out Matrix2x3FP32 sum)
|
||||
public static void Add(in FP32Matrix2x3 matrix1, in FP32Matrix2x3 matrix2, out FP32Matrix2x3 sum)
|
||||
{
|
||||
sum.r1c1 = matrix1.r1c1 + matrix2.r1c1;
|
||||
sum.r1c2 = matrix1.r1c2 + matrix2.r1c2;
|
||||
|
|
@ -175,7 +192,7 @@ namespace BGC
|
|||
sum.r3c2 = matrix1.r3c2 + matrix2.r3c2;
|
||||
}
|
||||
|
||||
public static void Subtract(in Matrix2x3FP32 minuend, in Matrix2x3FP32 subtrahend, out Matrix2x3FP32 difference)
|
||||
public static void Subtract(in FP32Matrix2x3 minuend, in FP32Matrix2x3 subtrahend, out FP32Matrix2x3 difference)
|
||||
{
|
||||
difference.r1c1 = minuend.r1c1 - subtrahend.r1c1;
|
||||
difference.r1c2 = minuend.r1c2 - subtrahend.r1c2;
|
||||
|
|
@ -187,7 +204,7 @@ namespace BGC
|
|||
difference.r3c2 = minuend.r3c2 - subtrahend.r3c2;
|
||||
}
|
||||
|
||||
public static void Multiply(in Matrix2x3FP32 multiplicand, float multiplier, out Matrix2x3FP32 product)
|
||||
public static void Multiply(in FP32Matrix2x3 multiplicand, float multiplier, out FP32Matrix2x3 product)
|
||||
{
|
||||
product.r1c1 = multiplicand.r1c1 * multiplier;
|
||||
product.r1c2 = multiplicand.r1c2 * multiplier;
|
||||
|
|
@ -199,19 +216,19 @@ namespace BGC
|
|||
product.r3c2 = multiplicand.r3c2 * multiplier;
|
||||
}
|
||||
|
||||
public static void Divide(in Matrix2x3FP32 dividend, float divisor, out Matrix2x3FP32 quotient)
|
||||
public static void Divide(in FP32Matrix2x3 dividend, float divisor, out FP32Matrix2x3 quotient)
|
||||
{
|
||||
Multiply(dividend, 1.0f / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void GetRightProduct(in Matrix2x3FP32 matrix, in Vector2FP32 vector, out Vector3FP32 result)
|
||||
public static void GetRightProduct(in FP32Matrix2x3 matrix, in FP32Vector2 vector, out FP32Vector3 result)
|
||||
{
|
||||
result.x1 = matrix.r1c1 * vector.x1 + matrix.r1c2 * vector.x2;
|
||||
result.x2 = matrix.r2c1 * vector.x1 + matrix.r2c2 * vector.x2;
|
||||
result.x3 = matrix.r3c1 * vector.x1 + matrix.r3c2 * vector.x2;
|
||||
}
|
||||
|
||||
public static void GetLeftProduct(in Vector3FP32 vector, in Matrix2x3FP32 matrix, out Vector2FP32 result)
|
||||
public static void GetLeftProduct(in FP32Vector3 vector, in FP32Matrix2x3 matrix, out FP32Vector2 result)
|
||||
{
|
||||
result.x1 = vector.x1 * matrix.r1c1 + vector.x2 * matrix.r2c1 + vector.x3 * matrix.r3c1;
|
||||
result.x2 = vector.x1 * matrix.r1c2 + vector.x2 * matrix.r2c2 + vector.x3 * matrix.r3c2;
|
||||
|
|
@ -1,16 +1,31 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 11 Nov 2024
|
||||
*/
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public struct Matrix3x2FP32
|
||||
public struct FP32Matrix3x2
|
||||
{
|
||||
public float r1c1 = 0.0f, r1c2 = 0.0f, r1c3 = 0.0f;
|
||||
public float r2c1 = 0.0f, r2c2 = 0.0f, r2c3 = 0.0f;
|
||||
|
||||
public Matrix3x2FP32(in Matrix3x2FP32 matrix)
|
||||
public FP32Matrix3x2(in FP32Matrix3x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -21,7 +36,7 @@ namespace BGC
|
|||
this.r2c3 = matrix.r2c3;
|
||||
}
|
||||
|
||||
public Matrix3x2FP32(in Matrix3x2FP64 matrix)
|
||||
public FP32Matrix3x2(in FP64Matrix3x2 matrix)
|
||||
{
|
||||
this.r1c1 = (float) matrix.r1c1;
|
||||
this.r1c2 = (float) matrix.r1c2;
|
||||
|
|
@ -32,7 +47,7 @@ namespace BGC
|
|||
this.r2c3 = (float) matrix.r2c3;
|
||||
}
|
||||
|
||||
public Matrix3x2FP32(in Matrix2x3FP32 matrix)
|
||||
public FP32Matrix3x2(in FP32Matrix2x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r2c1;
|
||||
|
|
@ -43,7 +58,7 @@ namespace BGC
|
|||
this.r2c3 = matrix.r3c2;
|
||||
}
|
||||
|
||||
public Matrix3x2FP32(in Matrix2x3FP64 matrix)
|
||||
public FP32Matrix3x2(in FP64Matrix2x3 matrix)
|
||||
{
|
||||
this.r1c1 = (float) matrix.r1c1;
|
||||
this.r1c2 = (float) matrix.r2c1;
|
||||
|
|
@ -65,7 +80,7 @@ namespace BGC
|
|||
this.r2c3 = 0.0f;
|
||||
}
|
||||
|
||||
public void SetValues(in Matrix3x2FP32 matrix)
|
||||
public void SetValues(in FP32Matrix3x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -76,7 +91,7 @@ namespace BGC
|
|||
this.r2c3 = matrix.r2c3;
|
||||
}
|
||||
|
||||
public void SetValues(in Matrix3x2FP64 matrix)
|
||||
public void SetValues(in FP64Matrix3x2 matrix)
|
||||
{
|
||||
this.r1c1 = (float) matrix.r1c1;
|
||||
this.r1c2 = (float) matrix.r1c2;
|
||||
|
|
@ -87,7 +102,7 @@ namespace BGC
|
|||
this.r2c3 = (float) matrix.r2c3;
|
||||
}
|
||||
|
||||
public void SetTransposed(in Matrix2x3FP32 matrix)
|
||||
public void SetTransposed(in FP32Matrix2x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r2c1;
|
||||
|
|
@ -98,7 +113,7 @@ namespace BGC
|
|||
this.r2c3 = matrix.r3c2;
|
||||
}
|
||||
|
||||
public void SetTransposed(in Matrix2x3FP64 matrix)
|
||||
public void SetTransposed(in FP64Matrix2x3 matrix)
|
||||
{
|
||||
this.r1c1 = (float) matrix.r1c1;
|
||||
this.r1c2 = (float) matrix.r2c1;
|
||||
|
|
@ -141,7 +156,7 @@ namespace BGC
|
|||
this.r2c3 = r2;
|
||||
}
|
||||
|
||||
public void AppendScaled(in Matrix3x2FP32 matrix, float scale)
|
||||
public void AppendScaled(in FP32Matrix3x2 matrix, float scale)
|
||||
{
|
||||
this.r1c1 += matrix.r1c1 * scale;
|
||||
this.r1c2 += matrix.r1c2 * scale;
|
||||
|
|
@ -152,7 +167,7 @@ namespace BGC
|
|||
this.r2c3 += matrix.r2c3 * scale;
|
||||
}
|
||||
|
||||
public static void Add(in Matrix3x2FP32 matrix1, in Matrix3x2FP32 matrix2, out Matrix3x2FP32 sum)
|
||||
public static void Add(in FP32Matrix3x2 matrix1, in FP32Matrix3x2 matrix2, out FP32Matrix3x2 sum)
|
||||
{
|
||||
sum.r1c1 = matrix1.r1c1 + matrix2.r1c1;
|
||||
sum.r1c2 = matrix1.r1c2 + matrix2.r1c2;
|
||||
|
|
@ -163,7 +178,7 @@ namespace BGC
|
|||
sum.r2c3 = matrix1.r2c3 + matrix2.r2c3;
|
||||
}
|
||||
|
||||
public static void Subtract(in Matrix3x2FP32 minuend, in Matrix3x2FP32 subtrahend, out Matrix3x2FP32 difference)
|
||||
public static void Subtract(in FP32Matrix3x2 minuend, in FP32Matrix3x2 subtrahend, out FP32Matrix3x2 difference)
|
||||
{
|
||||
difference.r1c1 = minuend.r1c1 - subtrahend.r1c1;
|
||||
difference.r1c2 = minuend.r1c2 - subtrahend.r1c2;
|
||||
|
|
@ -174,7 +189,7 @@ namespace BGC
|
|||
difference.r2c3 = minuend.r2c3 - subtrahend.r2c3;
|
||||
}
|
||||
|
||||
public static void Multiply(in Matrix3x2FP32 multiplicand, float multiplier, out Matrix3x2FP32 product)
|
||||
public static void Multiply(in FP32Matrix3x2 multiplicand, float multiplier, out FP32Matrix3x2 product)
|
||||
{
|
||||
product.r1c1 = multiplicand.r1c1 * multiplier;
|
||||
product.r1c2 = multiplicand.r1c2 * multiplier;
|
||||
|
|
@ -185,18 +200,18 @@ namespace BGC
|
|||
product.r2c3 = multiplicand.r2c3 * multiplier;
|
||||
}
|
||||
|
||||
public static void Divide(in Matrix3x2FP32 dividend, float divisor, out Matrix3x2FP32 quotient)
|
||||
public static void Divide(in FP32Matrix3x2 dividend, float divisor, out FP32Matrix3x2 quotient)
|
||||
{
|
||||
Multiply(dividend, 1.0f / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void GetRightProduct(in Matrix3x2FP32 matrix, in Vector3FP32 vector, out Vector2FP32 result)
|
||||
public static void GetRightProduct(in FP32Matrix3x2 matrix, in FP32Vector3 vector, out FP32Vector2 result)
|
||||
{
|
||||
result.x1 = matrix.r1c1 * vector.x1 + matrix.r1c2 * vector.x2 + matrix.r1c3 * vector.x3;
|
||||
result.x2 = matrix.r2c1 * vector.x1 + matrix.r2c2 * vector.x2 + matrix.r2c3 * vector.x3;
|
||||
}
|
||||
|
||||
public static void GetLeftProduct(in Vector2FP32 vector, in Matrix3x2FP32 matrix, out Vector3FP32 result)
|
||||
public static void GetLeftProduct(in FP32Vector2 vector, in FP32Matrix3x2 matrix, out FP32Vector3 result)
|
||||
{
|
||||
result.x1 = vector.x1 * matrix.r1c1 + vector.x2 * matrix.r2c1;
|
||||
result.x2 = vector.x1 * matrix.r1c2 + vector.x2 * matrix.r2c2;
|
||||
|
|
@ -1,25 +1,42 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 10 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public struct Matrix3x3FP32
|
||||
public struct FP32Matrix3x3
|
||||
{
|
||||
public float r1c1 = 0.0f, r1c2 = 0.0f, r1c3 = 0.0f;
|
||||
public float r2c1 = 0.0f, r2c2 = 0.0f, r2c3 = 0.0f;
|
||||
public float r3c1 = 0.0f, r3c2 = 0.0f, r3c3 = 0.0f;
|
||||
|
||||
public Matrix3x3FP32(float d1, float d2, float d3)
|
||||
public FP32Matrix3x3(float d1, float d2, float d3)
|
||||
{
|
||||
this.r1c1 = d1;
|
||||
this.r2c2 = d2;
|
||||
this.r3c3 = d3;
|
||||
}
|
||||
|
||||
public Matrix3x3FP32(in Matrix3x3FP32 matrix)
|
||||
public FP32Matrix3x3(in FP32Matrix3x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -34,7 +51,7 @@ namespace BGC
|
|||
this.r3c3 = matrix.r3c3;
|
||||
}
|
||||
|
||||
public Matrix3x3FP32(in Matrix3x3FP64 matrix)
|
||||
public FP32Matrix3x3(in FP64Matrix3x3 matrix)
|
||||
{
|
||||
this.r1c1 = (float)matrix.r1c1;
|
||||
this.r1c2 = (float)matrix.r1c2;
|
||||
|
|
@ -58,7 +75,8 @@ namespace BGC
|
|||
|
||||
public readonly bool IsSingular()
|
||||
{
|
||||
return UtilityFP32.IsZero(this.GetDeterminant());
|
||||
float determinant = this.GetDeterminant();
|
||||
return -FP32Utility.EPSYLON <= determinant && determinant <= FP32Utility.EPSYLON;
|
||||
}
|
||||
|
||||
public void Transpose()
|
||||
|
|
@ -72,8 +90,7 @@ namespace BGC
|
|||
{
|
||||
float determinant = this.GetDeterminant();
|
||||
|
||||
if (UtilityFP32.IsZero(determinant))
|
||||
{
|
||||
if (-FP32Utility.EPSYLON <= determinant && determinant <= FP32Utility.EPSYLON) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -151,7 +168,7 @@ namespace BGC
|
|||
this.r2c3 = d3;
|
||||
}
|
||||
|
||||
public void Set(in Matrix3x3FP32 matrix)
|
||||
public void SetValues(in FP32Matrix3x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -166,7 +183,7 @@ namespace BGC
|
|||
this.r3c3 = matrix.r3c3;
|
||||
}
|
||||
|
||||
public void Set(in Matrix3x3FP64 matrix)
|
||||
public void SetValues(in FP64Matrix3x3 matrix)
|
||||
{
|
||||
this.r1c1 = (float)matrix.r1c1;
|
||||
this.r1c2 = (float)matrix.r1c2;
|
||||
|
|
@ -181,6 +198,69 @@ namespace BGC
|
|||
this.r3c3 = (float)matrix.r3c3;
|
||||
}
|
||||
|
||||
public void SetTransposedOf(in FP32Matrix3x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r2c2 = matrix.r2c2;
|
||||
this.r3c3 = matrix.r3c3;
|
||||
|
||||
(this.r1c2, this.r2c1) = (matrix.r2c1, matrix.r1c2);
|
||||
(this.r1c3, this.r3c1) = (matrix.r3c1, matrix.r1c3);
|
||||
(this.r2c3, this.r3c2) = (matrix.r3c2, matrix.r2c3);
|
||||
}
|
||||
|
||||
public void SetTransposedOf(in FP64Matrix3x3 matrix)
|
||||
{
|
||||
this.r1c1 = (float)matrix.r1c1;
|
||||
this.r1c2 = (float)matrix.r2c1;
|
||||
this.r1c3 = (float)matrix.r3c1;
|
||||
|
||||
this.r2c1 = (float)matrix.r1c2;
|
||||
this.r2c2 = (float)matrix.r2c2;
|
||||
this.r2c3 = (float)matrix.r3c2;
|
||||
|
||||
this.r3c1 = (float)matrix.r1c3;
|
||||
this.r3c2 = (float)matrix.r2c3;
|
||||
this.r3c3 = (float)matrix.r3c3;
|
||||
}
|
||||
|
||||
public bool SetInvertedOf(in FP32Matrix3x3 matrix)
|
||||
{
|
||||
float determinant = matrix.GetDeterminant();
|
||||
|
||||
if (-FP32Utility.EPSYLON <= determinant && determinant <= FP32Utility.EPSYLON) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float r1c1 = matrix.r2c2 * matrix.r3c3 - matrix.r2c3 * matrix.r3c2;
|
||||
float r1c2 = matrix.r1c3 * matrix.r3c2 - matrix.r1c2 * matrix.r3c3;
|
||||
float r1c3 = matrix.r1c2 * matrix.r2c3 - matrix.r1c3 * matrix.r2c2;
|
||||
|
||||
float r2c1 = matrix.r2c3 * matrix.r3c1 - matrix.r2c1 * matrix.r3c3;
|
||||
float r2c2 = matrix.r1c1 * matrix.r3c3 - matrix.r1c3 * matrix.r3c1;
|
||||
float r2c3 = matrix.r1c3 * matrix.r2c1 - matrix.r1c1 * matrix.r2c3;
|
||||
|
||||
float r3c1 = matrix.r2c1 * matrix.r3c2 - matrix.r2c2 * matrix.r3c1;
|
||||
float r3c2 = matrix.r1c2 * matrix.r3c1 - matrix.r1c1 * matrix.r3c2;
|
||||
float r3c3 = matrix.r1c1 * matrix.r2c2 - matrix.r1c2 * matrix.r2c1;
|
||||
|
||||
float mutiplier = 1.0f / determinant;
|
||||
|
||||
this.r1c1 = r1c1 * mutiplier;
|
||||
this.r1c2 = r1c2 * mutiplier;
|
||||
this.r1c3 = r1c3 * mutiplier;
|
||||
|
||||
this.r2c1 = r2c1 * mutiplier;
|
||||
this.r2c2 = r2c2 * mutiplier;
|
||||
this.r2c3 = r2c3 * mutiplier;
|
||||
|
||||
this.r3c1 = r3c1 * mutiplier;
|
||||
this.r3c2 = r3c2 * mutiplier;
|
||||
this.r3c3 = r3c3 * mutiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetRow1(float c1, float c2, float c3)
|
||||
{
|
||||
this.r1c1 = c1;
|
||||
|
|
@ -223,56 +303,22 @@ namespace BGC
|
|||
this.r3c3 = r3;
|
||||
}
|
||||
|
||||
public static void MakeTransposed(in Matrix3x3FP32 matrix, out Matrix3x3FP32 transposed)
|
||||
public void AppendScaled(in FP32Matrix3x3 matrix, float scale)
|
||||
{
|
||||
transposed.r1c1 = matrix.r1c1;
|
||||
transposed.r2c2 = matrix.r2c2;
|
||||
transposed.r3c3 = matrix.r3c3;
|
||||
this.r1c1 += matrix.r1c1* scale;
|
||||
this.r1c2 += matrix.r1c2* scale;
|
||||
this.r1c3 += matrix.r1c3* scale;
|
||||
|
||||
(transposed.r1c2, transposed.r2c1) = (matrix.r2c1, matrix.r1c2);
|
||||
(transposed.r1c3, transposed.r3c1) = (matrix.r3c1, matrix.r1c3);
|
||||
(transposed.r2c3, transposed.r3c2) = (matrix.r3c2, matrix.r2c3);
|
||||
this.r2c1 += matrix.r2c1* scale;
|
||||
this.r2c2 += matrix.r2c2* scale;
|
||||
this.r2c3 += matrix.r2c3* scale;
|
||||
|
||||
this.r3c1 += matrix.r3c1* scale;
|
||||
this.r3c2 += matrix.r3c2* scale;
|
||||
this.r3c3 += matrix.r3c3* scale;
|
||||
}
|
||||
|
||||
public static bool MakeInverted(in Matrix3x3FP32 matrix, out Matrix3x3FP32 inverted)
|
||||
{
|
||||
float determinant = matrix.GetDeterminant();
|
||||
|
||||
if (UtilityFP32.IsZero(determinant)) {
|
||||
LoadZero(out inverted);
|
||||
return false;
|
||||
}
|
||||
|
||||
float r1c1 = matrix.r2c2 * matrix.r3c3 - matrix.r2c3 * matrix.r3c2;
|
||||
float r1c2 = matrix.r1c3 * matrix.r3c2 - matrix.r1c2 * matrix.r3c3;
|
||||
float r1c3 = matrix.r1c2 * matrix.r2c3 - matrix.r1c3 * matrix.r2c2;
|
||||
|
||||
float r2c1 = matrix.r2c3 * matrix.r3c1 - matrix.r2c1 * matrix.r3c3;
|
||||
float r2c2 = matrix.r1c1 * matrix.r3c3 - matrix.r1c3 * matrix.r3c1;
|
||||
float r2c3 = matrix.r1c3 * matrix.r2c1 - matrix.r1c1 * matrix.r2c3;
|
||||
|
||||
float r3c1 = matrix.r2c1 * matrix.r3c2 - matrix.r2c2 * matrix.r3c1;
|
||||
float r3c2 = matrix.r1c2 * matrix.r3c1 - matrix.r1c1 * matrix.r3c2;
|
||||
float r3c3 = matrix.r1c1 * matrix.r2c2 - matrix.r1c2 * matrix.r2c1;
|
||||
|
||||
float mutiplier = 1.0f / determinant;
|
||||
|
||||
inverted.r1c1 = r1c1 * mutiplier;
|
||||
inverted.r1c2 = r1c2 * mutiplier;
|
||||
inverted.r1c3 = r1c3 * mutiplier;
|
||||
|
||||
inverted.r2c1 = r2c1 * mutiplier;
|
||||
inverted.r2c2 = r2c2 * mutiplier;
|
||||
inverted.r2c3 = r2c3 * mutiplier;
|
||||
|
||||
inverted.r3c1 = r3c1 * mutiplier;
|
||||
inverted.r3c2 = r3c2 * mutiplier;
|
||||
inverted.r3c3 = r3c3 * mutiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Add(in Matrix3x3FP32 matrix1, in Matrix3x3FP32 matrix2, out Matrix3x3FP32 sum)
|
||||
public static void Add(in FP32Matrix3x3 matrix1, in FP32Matrix3x3 matrix2, out FP32Matrix3x3 sum)
|
||||
{
|
||||
sum.r1c1 = matrix1.r1c1 + matrix2.r1c1;
|
||||
sum.r1c2 = matrix1.r1c2 + matrix2.r1c2;
|
||||
|
|
@ -287,22 +333,7 @@ namespace BGC
|
|||
sum.r3c3 = matrix1.r3c3 + matrix2.r3c3;
|
||||
}
|
||||
|
||||
public static void AddScaled(in Matrix3x3FP32 basicMatrix, in Matrix3x3FP32 scalableMatrix, float scale, out Matrix3x3FP32 sum)
|
||||
{
|
||||
sum.r1c1 = basicMatrix.r1c1 + scalableMatrix.r1c1 * scale;
|
||||
sum.r1c2 = basicMatrix.r1c2 + scalableMatrix.r1c2 * scale;
|
||||
sum.r1c3 = basicMatrix.r1c3 + scalableMatrix.r1c3 * scale;
|
||||
|
||||
sum.r2c1 = basicMatrix.r2c1 + scalableMatrix.r2c1 * scale;
|
||||
sum.r2c2 = basicMatrix.r2c2 + scalableMatrix.r2c2 * scale;
|
||||
sum.r2c3 = basicMatrix.r2c3 + scalableMatrix.r2c3 * scale;
|
||||
|
||||
sum.r3c1 = basicMatrix.r3c1 + scalableMatrix.r3c1 * scale;
|
||||
sum.r3c2 = basicMatrix.r3c2 + scalableMatrix.r3c2 * scale;
|
||||
sum.r3c3 = basicMatrix.r3c3 + scalableMatrix.r3c3 * scale;
|
||||
}
|
||||
|
||||
public static void Subtract(in Matrix3x3FP32 minuend, in Matrix3x3FP32 subtrahend, out Matrix3x3FP32 difference)
|
||||
public static void Subtract(in FP32Matrix3x3 minuend, in FP32Matrix3x3 subtrahend, out FP32Matrix3x3 difference)
|
||||
{
|
||||
difference.r1c1 = minuend.r1c1 - subtrahend.r1c1;
|
||||
difference.r1c2 = minuend.r1c2 - subtrahend.r1c2;
|
||||
|
|
@ -317,7 +348,7 @@ namespace BGC
|
|||
difference.r3c3 = minuend.r3c3 - subtrahend.r3c3;
|
||||
}
|
||||
|
||||
public static void Multiply(in Matrix3x3FP32 multiplicand, float multiplier, out Matrix3x3FP32 product)
|
||||
public static void Multiply(in FP32Matrix3x3 multiplicand, float multiplier, out FP32Matrix3x3 product)
|
||||
{
|
||||
product.r1c1 = multiplicand.r1c1 * multiplier;
|
||||
product.r1c2 = multiplicand.r1c2 * multiplier;
|
||||
|
|
@ -332,12 +363,12 @@ namespace BGC
|
|||
product.r3c3 = multiplicand.r3c3 * multiplier;
|
||||
}
|
||||
|
||||
public static void Divide(in Matrix3x3FP32 dividend, float divisor, out Matrix3x3FP32 quotient)
|
||||
public static void Divide(in FP32Matrix3x3 dividend, float divisor, out FP32Matrix3x3 quotient)
|
||||
{
|
||||
Multiply(dividend, 1.0f / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void RightProduct(in Matrix3x3FP32 matrix, in Vector3FP32 vector, out Vector3FP32 result)
|
||||
public static void GetRightProduct(in FP32Matrix3x3 matrix, in FP32Vector3 vector, out FP32Vector3 result)
|
||||
{
|
||||
float x1 = matrix.r1c1 * vector.x1 + matrix.r1c2 * vector.x2 + matrix.r1c3 * vector.x3;
|
||||
float x2 = matrix.r2c1 * vector.x1 + matrix.r2c2 * vector.x2 + matrix.r2c3 * vector.x3;
|
||||
|
|
@ -348,7 +379,7 @@ namespace BGC
|
|||
result.x3 = x3;
|
||||
}
|
||||
|
||||
public static void LeftProduct(in Vector3FP32 vector, in Matrix3x3FP32 matrix, out Vector3FP32 result)
|
||||
public static void GetLeftProduct(in FP32Vector3 vector, in FP32Matrix3x3 matrix, out FP32Vector3 result)
|
||||
{
|
||||
float x1 = vector.x1 * matrix.r1c1 + vector.x2 * matrix.r2c1 + vector.x3 * matrix.r3c1;
|
||||
float x2 = vector.x1 * matrix.r1c2 + vector.x2 * matrix.r2c2 + vector.x3 * matrix.r3c2;
|
||||
|
|
@ -359,7 +390,7 @@ namespace BGC
|
|||
result.x3 = x3;
|
||||
}
|
||||
|
||||
public static void LoadZero(out Matrix3x3FP32 matrix)
|
||||
public static void LoadZero(out FP32Matrix3x3 matrix)
|
||||
{
|
||||
matrix.r1c1 = 0.0f;
|
||||
matrix.r1c2 = 0.0f;
|
||||
|
|
@ -374,7 +405,7 @@ namespace BGC
|
|||
matrix.r3c3 = 0.0f;
|
||||
}
|
||||
|
||||
public static void LoadIdentity(out Matrix3x3FP32 matrix)
|
||||
public static void LoadIdentity(out FP32Matrix3x3 matrix)
|
||||
{
|
||||
matrix.r1c1 = 1.0f;
|
||||
matrix.r1c2 = 0.0f;
|
||||
|
|
@ -389,7 +420,7 @@ namespace BGC
|
|||
matrix.r3c3 = 1.0f;
|
||||
}
|
||||
|
||||
public static void LoadDiagonal(float d1, float d2, float d3, out Matrix3x3FP32 matrix)
|
||||
public static void LoadDiagonal(float d1, float d2, float d3, out FP32Matrix3x3 matrix)
|
||||
{
|
||||
matrix.r1c1 = d1;
|
||||
matrix.r1c2 = 0.0f;
|
||||
|
|
@ -1,14 +1,30 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 11 Nov 2024
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public class MatrixProductFP32
|
||||
public class FP32MatrixProduct
|
||||
{
|
||||
public static void Get2x2At2x2(in Matrix2x2FP32 left, in Matrix2x2FP32 right, out Matrix2x2FP32 product)
|
||||
public static void Get2x2At2x2(in FP32Matrix2x2 left, in FP32Matrix2x2 right, out FP32Matrix2x2 product)
|
||||
{
|
||||
float r1c1 = left.r1c1 * right.r1c1 + left.r1c2 * right.r2c1;
|
||||
float r1c2 = left.r1c1 * right.r1c2 + left.r1c2 * right.r2c2;
|
||||
|
|
@ -23,7 +39,7 @@ namespace BGC
|
|||
product.r2c2 = r2c2;
|
||||
}
|
||||
|
||||
public static void Get2x2At3x2(in Matrix2x2FP32 left, in Matrix3x2FP32 right, out Matrix3x2FP32 product)
|
||||
public static void Get2x2At3x2(in FP32Matrix2x2 left, in FP32Matrix3x2 right, out FP32Matrix3x2 product)
|
||||
{
|
||||
float r1c1 = left.r1c1 * right.r1c1 + left.r1c2 * right.r2c1;
|
||||
float r1c2 = left.r1c1 * right.r1c2 + left.r1c2 * right.r2c2;
|
||||
|
|
@ -42,7 +58,7 @@ namespace BGC
|
|||
product.r2c3 = r2c3;
|
||||
}
|
||||
|
||||
public static void Get2x3At2x2(in Matrix2x3FP32 left, in Matrix2x2FP32 right, out Matrix2x3FP32 product)
|
||||
public static void Get2x3At2x2(in FP32Matrix2x3 left, in FP32Matrix2x2 right, out FP32Matrix2x3 product)
|
||||
{
|
||||
float r1c1 = left.r1c1 * right.r1c1 + left.r1c2 * right.r2c1;
|
||||
float r1c2 = left.r1c1 * right.r1c2 + left.r1c2 * right.r2c2;
|
||||
|
|
@ -63,7 +79,7 @@ namespace BGC
|
|||
product.r3c2 = r3c2;
|
||||
}
|
||||
|
||||
public static void Get2x3At3x2(in Matrix2x3FP32 left, in Matrix3x2FP32 right, out Matrix3x3FP32 product)
|
||||
public static void Get2x3At3x2(in FP32Matrix2x3 left, in FP32Matrix3x2 right, out FP32Matrix3x3 product)
|
||||
{
|
||||
product.r1c1 = left.r1c1 * right.r1c1 + left.r1c2 * right.r2c1;
|
||||
product.r1c2 = left.r1c1 * right.r1c2 + left.r1c2 * right.r2c2;
|
||||
|
|
@ -78,7 +94,7 @@ namespace BGC
|
|||
product.r3c3 = left.r3c1 * right.r1c2 + left.r3c2 * right.r2c3;
|
||||
}
|
||||
|
||||
public static void Get3x2At3x3(in Matrix3x2FP32 left, in Matrix3x3FP32 right, out Matrix3x2FP32 product)
|
||||
public static void Get3x2At3x3(in FP32Matrix3x2 left, in FP32Matrix3x3 right, out FP32Matrix3x2 product)
|
||||
{
|
||||
float r1c1 = left.r1c1 * right.r1c1 + left.r1c2 * right.r2c1 + left.r1c3 * right.r3c1;
|
||||
float r1c2 = left.r1c1 * right.r1c2 + left.r1c2 * right.r2c2 + left.r1c3 * right.r3c2;
|
||||
|
|
@ -97,7 +113,7 @@ namespace BGC
|
|||
product.r2c3 = r2c3;
|
||||
}
|
||||
|
||||
public static void Get3x2At2x3(in Matrix3x2FP32 left, in Matrix2x3FP32 right, out Matrix2x2FP32 product)
|
||||
public static void Get3x2At2x3(in FP32Matrix3x2 left, in FP32Matrix2x3 right, out FP32Matrix2x2 product)
|
||||
{
|
||||
product.r1c1 = left.r1c1 * right.r1c1 + left.r1c2 * right.r2c1 + left.r1c3 * right.r3c1;
|
||||
product.r1c2 = left.r1c1 * right.r1c2 + left.r1c2 * right.r2c2 + left.r1c3 * right.r3c2;
|
||||
|
|
@ -106,7 +122,7 @@ namespace BGC
|
|||
product.r2c2 = left.r2c1 * right.r1c2 + left.r2c2 * right.r2c2 + left.r2c3 * right.r3c2;
|
||||
}
|
||||
|
||||
public static void Get3x3At2x3(in Matrix3x3FP32 left, in Matrix2x3FP32 right, out Matrix2x3FP32 product)
|
||||
public static void Get3x3At2x3(in FP32Matrix3x3 left, in FP32Matrix2x3 right, out FP32Matrix2x3 product)
|
||||
{
|
||||
float r1c1 = left.r1c1 * right.r1c1 + left.r1c2 * right.r2c1 + left.r1c3 * right.r3c1;
|
||||
float r1c2 = left.r1c1 * right.r1c2 + left.r1c2 * right.r2c2 + left.r1c3 * right.r3c2;
|
||||
|
|
@ -127,7 +143,7 @@ namespace BGC
|
|||
product.r3c2 = r3c2;
|
||||
}
|
||||
|
||||
public static void Get3x3At3x3(in Matrix3x3FP32 left, in Matrix3x3FP32 right, out Matrix3x3FP32 product)
|
||||
public static void Get3x3At3x3(in FP32Matrix3x3 left, in FP32Matrix3x3 right, out FP32Matrix3x3 product)
|
||||
{
|
||||
float r1c1 = left.r1c1 * right.r1c1 + left.r1c2 * right.r2c1 + left.r1c3 * right.r3c1;
|
||||
float r1c2 = left.r1c1 * right.r1c2 + left.r1c2 * right.r2c2 + left.r1c3 * right.r3c2;
|
||||
203
BasicGeometry/FP32Quaternion.cs
Normal file
203
BasicGeometry/FP32Quaternion.cs
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
using System;
|
||||
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public struct FP32Quaternion
|
||||
{
|
||||
public float s0 = 0.0f, x1 = 0.0f, x2 = 0.0f, x3 = 0.0f;
|
||||
|
||||
public FP32Quaternion(float s0, float x1, float x2, float x3)
|
||||
{
|
||||
this.s0 = s0;
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
}
|
||||
|
||||
public FP32Quaternion(in FP32Quaternion quaternion)
|
||||
{
|
||||
this.s0 = quaternion.s0;
|
||||
this.x1 = quaternion.x1;
|
||||
this.x2 = quaternion.x2;
|
||||
this.x3 = quaternion.x3;
|
||||
}
|
||||
|
||||
public FP32Quaternion(in FP64Quaternion quaternion)
|
||||
{
|
||||
this.s0 = (float)quaternion.s0;
|
||||
this.x1 = (float)quaternion.x1;
|
||||
this.x2 = (float)quaternion.x2;
|
||||
this.x3 = (float)quaternion.x3;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.s0 = 0.0f;
|
||||
this.x1 = 0.0f;
|
||||
this.x2 = 0.0f;
|
||||
this.x3 = 0.0f;
|
||||
}
|
||||
|
||||
public void Conjugate()
|
||||
{
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
this.x3 = -this.x3;
|
||||
}
|
||||
|
||||
public void SetValues(float s0, float x1, float x2, float x3)
|
||||
{
|
||||
this.s0 = s0;
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
}
|
||||
|
||||
public void SetValues(in FP32Quaternion quaternion)
|
||||
{
|
||||
this.s0 = quaternion.s0;
|
||||
this.x1 = quaternion.x1;
|
||||
this.x2 = quaternion.x2;
|
||||
this.x3 = quaternion.x3;
|
||||
}
|
||||
|
||||
public void SetValues(in FP64Quaternion quaternion)
|
||||
{
|
||||
this.s0 = (float)quaternion.s0;
|
||||
this.x1 = (float)quaternion.x1;
|
||||
this.x2 = (float)quaternion.x2;
|
||||
this.x3 = (float)quaternion.x3;
|
||||
}
|
||||
|
||||
public void SetConjugateOf(in FP32Quaternion quaternion)
|
||||
{
|
||||
this.s0 = quaternion.s0;
|
||||
this.x1 = -quaternion.x1;
|
||||
this.x2 = -quaternion.x2;
|
||||
this.x3 = -quaternion.x3;
|
||||
}
|
||||
|
||||
public readonly void MakeRotationMatrix(out FP32Matrix3x3 matrix)
|
||||
{
|
||||
float s0s0 = this.s0 * this.s0;
|
||||
float x1x1 = this.x1 * this.x1;
|
||||
float x2x2 = this.x2 * this.x2;
|
||||
float x3x3 = this.x3 * this.x3;
|
||||
|
||||
float squareModule = (s0s0 + x1x1) + (x2x2 + x3x3);
|
||||
|
||||
if (-FP32Utility.EPSYLON <= squareModule && squareModule <= FP32Utility.EPSYLON)
|
||||
{
|
||||
FP32Matrix3x3.LoadIdentity(out matrix);
|
||||
return;
|
||||
}
|
||||
|
||||
float corrector1;
|
||||
float corrector2;
|
||||
|
||||
if (1.0f - FP32Utility.TWO_EPSYLON <= squareModule && squareModule <= 1.0f + FP32Utility.TWO_EPSYLON) {
|
||||
corrector1 = 2.0f - squareModule;
|
||||
corrector2 = 2.0f * corrector1;
|
||||
}
|
||||
else {
|
||||
corrector1 = 1.0f / squareModule;
|
||||
corrector2 = 2.0f / squareModule;
|
||||
}
|
||||
|
||||
float s0x1 = this.s0 * this.x1;
|
||||
float s0x2 = this.s0 * this.x2;
|
||||
float s0x3 = this.s0 * this.x3;
|
||||
float x1x2 = this.x1 * this.x2;
|
||||
float x1x3 = this.x1 * this.x3;
|
||||
float x2x3 = this.x2 * this.x3;
|
||||
|
||||
matrix.r1c1 = corrector1 * ((s0s0 + x1x1) - (x2x2 + x3x3));
|
||||
matrix.r2c2 = corrector1 * ((s0s0 + x2x2) - (x1x1 + x3x3));
|
||||
matrix.r3c3 = corrector1 * ((s0s0 + x3x3) - (x1x1 + x2x2));
|
||||
|
||||
matrix.r1c2 = corrector2 * (x1x2 - s0x3);
|
||||
matrix.r2c3 = corrector2 * (x2x3 - s0x1);
|
||||
matrix.r3c1 = corrector2 * (x1x3 - s0x2);
|
||||
|
||||
matrix.r2c1 = corrector2 * (x1x2 + s0x3);
|
||||
matrix.r3c2 = corrector2 * (x2x3 + s0x1);
|
||||
matrix.r1c3 = corrector2 * (x1x3 + s0x2);
|
||||
}
|
||||
|
||||
public readonly void MakeReverseMatrix(out FP32Matrix3x3 matrix)
|
||||
{
|
||||
float s0s0 = this.s0 * this.s0;
|
||||
float x1x1 = this.x1 * this.x1;
|
||||
float x2x2 = this.x2 * this.x2;
|
||||
float x3x3 = this.x3 * this.x3;
|
||||
|
||||
float squareModule = (s0s0 + x1x1) + (x2x2 + x3x3);
|
||||
|
||||
if (-FP32Utility.EPSYLON <= squareModule && squareModule <= FP32Utility.EPSYLON)
|
||||
{
|
||||
FP32Matrix3x3.LoadIdentity(out matrix);
|
||||
return;
|
||||
}
|
||||
|
||||
float corrector1;
|
||||
float corrector2;
|
||||
|
||||
if (1.0f - FP32Utility.TWO_EPSYLON <= squareModule && squareModule <= 1.0f + FP32Utility.TWO_EPSYLON) {
|
||||
corrector1 = 2.0f - squareModule;
|
||||
corrector2 = 2.0f * corrector1;
|
||||
}
|
||||
else {
|
||||
corrector1 = 1.0f / squareModule;
|
||||
corrector2 = 2.0f / squareModule;
|
||||
}
|
||||
|
||||
float s0x1 = this.s0 * this.x1;
|
||||
float s0x2 = this.s0 * this.x2;
|
||||
float s0x3 = this.s0 * this.x3;
|
||||
float x1x2 = this.x1 * this.x2;
|
||||
float x1x3 = this.x1 * this.x3;
|
||||
float x2x3 = this.x2 * this.x3;
|
||||
|
||||
matrix.r1c1 = corrector1 * ((s0s0 + x1x1) - (x2x2 + x3x3));
|
||||
matrix.r2c2 = corrector1 * ((s0s0 + x2x2) - (x1x1 + x3x3));
|
||||
matrix.r3c3 = corrector1 * ((s0s0 + x3x3) - (x1x1 + x2x2));
|
||||
|
||||
matrix.r1c2 = corrector2 * (x1x2 + s0x3);
|
||||
matrix.r2c3 = corrector2 * (x2x3 + s0x1);
|
||||
matrix.r3c1 = corrector2 * (x1x3 + s0x2);
|
||||
|
||||
matrix.r2c1 = corrector2 * (x1x2 - s0x3);
|
||||
matrix.r3c2 = corrector2 * (x2x3 - s0x1);
|
||||
matrix.r1c3 = corrector2 * (x1x3 - s0x2);
|
||||
}
|
||||
|
||||
public static void Add(in FP32Quaternion quaternion1, in FP32Quaternion quaternion2, out FP32Quaternion sum)
|
||||
{
|
||||
sum.s0 = quaternion1.s0 + quaternion2.s0;
|
||||
sum.x1 = quaternion1.x1 + quaternion2.x1;
|
||||
sum.x2 = quaternion1.x2 + quaternion2.x2;
|
||||
sum.x3 = quaternion1.x3 + quaternion2.x3;
|
||||
}
|
||||
|
||||
public static void Subtract(in FP32Quaternion minuend, in FP32Quaternion subtrahend, out FP32Quaternion difference)
|
||||
{
|
||||
difference.s0 = minuend.s0 - subtrahend.s0;
|
||||
difference.x1 = minuend.x1 - subtrahend.x1;
|
||||
difference.x2 = minuend.x2 - subtrahend.x2;
|
||||
difference.x3 = minuend.x3 - subtrahend.x3;
|
||||
}
|
||||
|
||||
public static void Multiply(in FP32Quaternion left, in FP32Quaternion right, out FP32Quaternion product)
|
||||
{
|
||||
float s0 = (left.s0 * right.s0 - left.x1 * right.x1) - (left.x2 * right.x2 + left.x3 * right.x3);
|
||||
float x1 = (left.x1 * right.s0 + left.s0 * right.x1) - (left.x3 * right.x2 - left.x2 * right.x3);
|
||||
float x2 = (left.x2 * right.s0 + left.s0 * right.x2) - (left.x1 * right.x3 - left.x3 * right.x1);
|
||||
float x3 = (left.x3 * right.s0 + left.s0 * right.x3) - (left.x2 * right.x1 - left.x1 * right.x2);
|
||||
|
||||
product.s0 = s0;
|
||||
product.x1 = x1;
|
||||
product.x2 = x2;
|
||||
product.x3 = x3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 18 Nov 2024
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public class RadianFP32
|
||||
public class FP32Radians
|
||||
{
|
||||
public const float PI = 3.1415926536f;
|
||||
public const float TWO_PI = 6.2831853072f;
|
||||
44
BasicGeometry/FP32Rotation3.cs
Normal file
44
BasicGeometry/FP32Rotation3.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* Date: 2 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public struct FP32Rotation3
|
||||
{
|
||||
private float angle = 0.0f;
|
||||
|
||||
private FP32Vector3 axis;
|
||||
|
||||
public FP32Rotation3(FP32Rotation3 rotation)
|
||||
{
|
||||
this.angle = rotation.angle;
|
||||
this.axis = rotation.axis;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.angle = 0.0f;
|
||||
this.axis.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 18 Nov 2024
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public class TurnFP32
|
||||
public class FP32Turns
|
||||
{
|
||||
public static float ToRadians(float turns)
|
||||
{
|
||||
return turns * RadianFP32.TWO_PI;
|
||||
return turns * FP32Radians.TWO_PI;
|
||||
}
|
||||
|
||||
public static float ToDegrees(float turns)
|
||||
|
|
@ -22,7 +22,7 @@ namespace BGC
|
|||
{
|
||||
if (toUnit == AngleUnit.RADIANS)
|
||||
{
|
||||
return turns * RadianFP32.TWO_PI;
|
||||
return turns * FP32Radians.TWO_PI;
|
||||
}
|
||||
|
||||
if (toUnit == AngleUnit.DEGREES)
|
||||
21
BasicGeometry/FP32Utility.cs
Normal file
21
BasicGeometry/FP32Utility.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public class FP32Utility
|
||||
{
|
||||
public const float EPSYLON = 5E-7f;
|
||||
public const float TWO_EPSYLON = 1E-6f;
|
||||
public const float SQUARE_EPSYLON = 2.5E-13f;
|
||||
|
||||
public const float EPSYLON_EFFECTIVENESS_LIMIT = 1.0f;
|
||||
|
||||
public const float ONE_THIRD = 0.333333333f;
|
||||
public const float ONE_SIXTH = 0.166666667f;
|
||||
public const float ONE_NINETH = 0.111111111f;
|
||||
|
||||
public const float GOLDEN_RATIO_HIGH = 1.618034f;
|
||||
public const float GOLDEN_RATIO_LOW = 0.618034f;
|
||||
}
|
||||
}
|
||||
|
||||
257
BasicGeometry/FP32Vector2.cs
Normal file
257
BasicGeometry/FP32Vector2.cs
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* Date: 1 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public struct FP32Vector2
|
||||
{
|
||||
public static readonly FP32Vector2 ZERO = new FP32Vector2(0.0f, 0.0f);
|
||||
|
||||
public float x1 = 0.0f;
|
||||
public float x2 = 0.0f;
|
||||
|
||||
public FP32Vector2(float x1, float x2)
|
||||
{
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
}
|
||||
|
||||
public FP32Vector2(in FP32Vector2 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
}
|
||||
|
||||
public FP32Vector2(in FP64Vector2 vector)
|
||||
{
|
||||
this.x1 = (float)vector.x1;
|
||||
this.x2 = (float)vector.x2;
|
||||
}
|
||||
|
||||
public readonly float GetSquareModule()
|
||||
{
|
||||
return this.x1 * this.x1 + this.x2 * this.x2;
|
||||
}
|
||||
|
||||
public readonly float GetModule()
|
||||
{
|
||||
return MathF.Sqrt(this.GetSquareModule());
|
||||
}
|
||||
|
||||
public int Normalize()
|
||||
{
|
||||
float squareModule = this.GetSquareModule();
|
||||
|
||||
if (1.0f - FP32Utility.TWO_EPSYLON <= squareModule && squareModule <= 1.0f + FP32Utility.TWO_EPSYLON)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (squareModule <= FP32Utility.SQUARE_EPSYLON)
|
||||
{
|
||||
this.Reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
float module = MathF.Sqrt(squareModule);
|
||||
|
||||
this.x1 /= module;
|
||||
this.x2 /= module;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public void Reverse()
|
||||
{
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
}
|
||||
|
||||
public readonly bool IsZero()
|
||||
{
|
||||
return this.GetSquareModule() <= FP32Utility.SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
public readonly bool IsUnit()
|
||||
{
|
||||
float squareModule = this.GetSquareModule();
|
||||
return 1.0f - FP32Utility.TWO_EPSYLON <= squareModule && squareModule <= FP32Utility.EPSYLON;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.x1 = 0.0f;
|
||||
this.x2 = 0.0f;
|
||||
}
|
||||
|
||||
public void SetValues(float x1, float x2)
|
||||
{
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
}
|
||||
|
||||
public void SetValues(in FP32Vector2 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
}
|
||||
|
||||
public void SetValues(in FP64Vector2 vector)
|
||||
{
|
||||
this.x1 = (float)vector.x1;
|
||||
this.x2 = (float)vector.x2;
|
||||
}
|
||||
|
||||
public void SetReverseOf(in FP32Vector2 vector)
|
||||
{
|
||||
this.x1 = -vector.x1;
|
||||
this.x2 = -vector.x2;
|
||||
}
|
||||
|
||||
public void SetReverseOf(in FP64Vector2 vector)
|
||||
{
|
||||
this.x1 = -(float)vector.x1;
|
||||
this.x2 = -(float)vector.x2;
|
||||
}
|
||||
|
||||
public void AppendScaled(FP32Vector2 summand, float scale)
|
||||
{
|
||||
this.x1 += summand.x1 * scale;
|
||||
this.x2 += summand.x2 * scale;
|
||||
}
|
||||
|
||||
public readonly override string ToString()
|
||||
{
|
||||
return String.Format("SPVector2({0}, {1})", this.x1, this.x2);
|
||||
}
|
||||
|
||||
public static void Add(in FP32Vector2 vector1, in FP32Vector2 vector2, out FP32Vector2 sum)
|
||||
{
|
||||
sum.x1 = vector1.x1 + vector2.x1;
|
||||
sum.x2 = vector1.x2 + vector2.x2;
|
||||
}
|
||||
|
||||
public static void Subtract(in FP32Vector2 minuend, in FP32Vector2 subtrahend, out FP32Vector2 difference)
|
||||
{
|
||||
difference.x1 = minuend.x1 - subtrahend.x1;
|
||||
difference.x2 = minuend.x2 - subtrahend.x2;
|
||||
}
|
||||
|
||||
public static void Multiply(in FP32Vector2 multiplicand, float multiplier, out FP32Vector2 product)
|
||||
{
|
||||
product.x1 = multiplicand.x1 * multiplier;
|
||||
product.x2 = multiplicand.x2 * multiplier;
|
||||
}
|
||||
|
||||
public static void Divide(in FP32Vector2 dividend, float divisor, out FP32Vector2 quotient)
|
||||
{
|
||||
Multiply(dividend, 1.0f / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void GetMean2(in FP32Vector2 vector1, in FP32Vector2 vector2, out FP32Vector2 result)
|
||||
{
|
||||
result.x1 = (vector1.x1 + vector2.x1) * 0.5f;
|
||||
result.x2 = (vector1.x2 + vector2.x2) * 0.5f;
|
||||
}
|
||||
|
||||
public static void GetMean3(in FP32Vector2 vector1, in FP32Vector2 vector2, in FP32Vector2 vector3, out FP32Vector2 result)
|
||||
{
|
||||
result.x1 = (vector1.x1 + vector2.x1 + vector3.x1) * FP32Utility.ONE_THIRD;
|
||||
result.x2 = (vector1.x2 + vector2.x2 + vector3.x2) * FP32Utility.ONE_THIRD;
|
||||
}
|
||||
|
||||
public static float GetScalarProduct(in FP32Vector2 vector1, in FP32Vector2 vector2)
|
||||
{
|
||||
return vector1.x1 * vector2.x1 + vector1.x2 * vector2.x2;
|
||||
}
|
||||
|
||||
public static float GetCrossProduct(in FP32Vector2 vector1, in FP32Vector2 vector2)
|
||||
{
|
||||
return vector1.x1 * vector2.x2 - vector1.x2 * vector2.x1;
|
||||
}
|
||||
|
||||
public static float GetAngle(in FP32Vector2 vector1, in FP32Vector2 vector2, AngleUnit unit)
|
||||
{
|
||||
float squareModule1 = vector1.GetSquareModule();
|
||||
|
||||
if (squareModule1 <= FP32Utility.SQUARE_EPSYLON)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float squareModule2 = vector2.GetSquareModule();
|
||||
|
||||
if (squareModule2 <= FP32Utility.SQUARE_EPSYLON)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float cosine = FP32Vector2.GetScalarProduct(vector1, vector2) / MathF.Sqrt(squareModule1 * squareModule2);
|
||||
|
||||
if (1.0f - FP32Utility.EPSYLON <= cosine)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (cosine <= -(1.0f - FP32Utility.EPSYLON))
|
||||
{
|
||||
return FP32Angle.GetHalfCircle(unit);
|
||||
}
|
||||
|
||||
return FP32Radians.ToUnits(MathF.Acos(cosine), unit);
|
||||
}
|
||||
|
||||
public static float GetSquareDistance(in FP32Vector2 vector1, in FP32Vector2 vector2)
|
||||
{
|
||||
float dx1 = vector1.x1 - vector2.x1;
|
||||
float dx2 = vector1.x2 - vector2.x2;
|
||||
|
||||
return dx1 * dx1 + dx2 * dx2;
|
||||
}
|
||||
|
||||
public static float GetDistance(in FP32Vector2 vector1, in FP32Vector2 vector2)
|
||||
{
|
||||
return MathF.Sqrt(GetSquareDistance(vector1, vector2));
|
||||
}
|
||||
|
||||
public static bool AreEqual(in FP32Vector2 vector1, in FP32Vector2 vector2)
|
||||
{
|
||||
float squareModule1 = vector1.GetSquareModule();
|
||||
float squareModule2 = vector2.GetSquareModule();
|
||||
float squareModule3 = GetSquareDistance(vector1, vector2);
|
||||
|
||||
// 2.0f means dimension amount
|
||||
if (squareModule1 < FP32Utility.EPSYLON_EFFECTIVENESS_LIMIT || squareModule2 < FP32Utility.EPSYLON_EFFECTIVENESS_LIMIT)
|
||||
{
|
||||
return squareModule3 < (2.0f * FP32Utility.SQUARE_EPSYLON);
|
||||
}
|
||||
|
||||
if (squareModule1 <= squareModule2)
|
||||
{
|
||||
return squareModule3 <= (2.0f * FP32Utility.SQUARE_EPSYLON) * squareModule2;
|
||||
}
|
||||
|
||||
return squareModule3 <= (2.0f * FP32Utility.SQUARE_EPSYLON) * squareModule1;
|
||||
}
|
||||
}
|
||||
}
|
||||
300
BasicGeometry/FP32Vector3.cs
Normal file
300
BasicGeometry/FP32Vector3.cs
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* Date: 1 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public struct FP32Vector3
|
||||
{
|
||||
public static readonly FP32Vector3 ZERO = new FP32Vector3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
public float x1 = 0.0f;
|
||||
public float x2 = 0.0f;
|
||||
public float x3 = 0.0f;
|
||||
|
||||
public FP32Vector3(float x1, float x2, float x3)
|
||||
{
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
}
|
||||
|
||||
public FP32Vector3(in FP32Vector3 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
this.x3 = vector.x3;
|
||||
}
|
||||
|
||||
public FP32Vector3(in FP64Vector3 vector)
|
||||
{
|
||||
this.x1 = (float)vector.x1;
|
||||
this.x2 = (float)vector.x2;
|
||||
this.x3 = (float)vector.x3;
|
||||
}
|
||||
|
||||
public readonly float GetSquareModule()
|
||||
{
|
||||
return this.x1 * this.x1 + this.x2 * this.x2 + this.x3 * this.x3;
|
||||
}
|
||||
|
||||
public readonly float GetModule()
|
||||
{
|
||||
return MathF.Sqrt(this.GetSquareModule());
|
||||
}
|
||||
|
||||
public int Normalize()
|
||||
{
|
||||
float squareModule = this.GetSquareModule();
|
||||
|
||||
if (1.0f - FP32Utility.TWO_EPSYLON <= squareModule && squareModule <= 1.0f + FP32Utility.TWO_EPSYLON)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (squareModule <= FP32Utility.SQUARE_EPSYLON)
|
||||
{
|
||||
this.Reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
float module = MathF.Sqrt(squareModule);
|
||||
|
||||
this.x1 /= module;
|
||||
this.x2 /= module;
|
||||
this.x3 /= module;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public void Reverse()
|
||||
{
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
this.x3 = -this.x3;
|
||||
}
|
||||
|
||||
public readonly bool IsZero()
|
||||
{
|
||||
return this.GetSquareModule() <= FP32Utility.SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
public readonly bool IsUnit()
|
||||
{
|
||||
float squareModule = this.GetSquareModule();
|
||||
return 1.0f - FP32Utility.TWO_EPSYLON <= squareModule && squareModule <= FP32Utility.EPSYLON;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.x1 = 0.0f;
|
||||
this.x2 = 0.0f;
|
||||
this.x3 = 0.0f;
|
||||
}
|
||||
|
||||
public void SetValues(float x1, float x2, float x3)
|
||||
{
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
}
|
||||
|
||||
public void SetValues(in FP64Vector3 vector)
|
||||
{
|
||||
this.x1 = (float)vector.x1;
|
||||
this.x2 = (float)vector.x2;
|
||||
this.x3 = (float)vector.x3;
|
||||
}
|
||||
|
||||
public void SetValues(in FP32Vector3 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
this.x3 = vector.x3;
|
||||
}
|
||||
|
||||
public void SetReverseOf(in FP32Vector3 vector)
|
||||
{
|
||||
this.x1 = -vector.x1;
|
||||
this.x2 = -vector.x2;
|
||||
this.x3 = -vector.x3;
|
||||
}
|
||||
|
||||
public void SetReverseOf(in FP64Vector3 vector)
|
||||
{
|
||||
this.x1 = -(float)vector.x1;
|
||||
this.x2 = -(float)vector.x2;
|
||||
this.x3 = -(float)vector.x3;
|
||||
}
|
||||
|
||||
public void AppendScaled(FP32Vector3 summand, float scale)
|
||||
{
|
||||
this.x1 += summand.x1 * scale;
|
||||
this.x2 += summand.x2 * scale;
|
||||
this.x3 += summand.x3 * scale;
|
||||
}
|
||||
|
||||
public readonly override string ToString()
|
||||
{
|
||||
return String.Format("SPVector3({0}, {1}, {2})", this.x1, this.x2, this.x3);
|
||||
}
|
||||
|
||||
public static void Add(in FP32Vector3 vector1, in FP32Vector3 vector2, out FP32Vector3 sum)
|
||||
{
|
||||
sum.x1 = vector1.x1 + vector2.x1;
|
||||
sum.x2 = vector1.x2 + vector2.x2;
|
||||
sum.x3 = vector1.x3 + vector2.x3;
|
||||
}
|
||||
|
||||
public static void Subtract(in FP32Vector3 minuend, in FP32Vector3 subtrahend, out FP32Vector3 difference)
|
||||
{
|
||||
difference.x1 = minuend.x1 - subtrahend.x1;
|
||||
difference.x2 = minuend.x2 - subtrahend.x2;
|
||||
difference.x3 = minuend.x3 - subtrahend.x3;
|
||||
}
|
||||
|
||||
public static void Multiply(in FP32Vector3 multiplicand, float multiplier, out FP32Vector3 product)
|
||||
{
|
||||
product.x1 = multiplicand.x1 * multiplier;
|
||||
product.x2 = multiplicand.x2 * multiplier;
|
||||
product.x3 = multiplicand.x3 * multiplier;
|
||||
}
|
||||
|
||||
public static void Divide(in FP32Vector3 dividend, float divisor, out FP32Vector3 quotient)
|
||||
{
|
||||
Multiply(dividend, 1.0f / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void GetMean2(in FP32Vector3 vector1, in FP32Vector3 vector2, out FP32Vector3 result)
|
||||
{
|
||||
result.x1 = (vector1.x1 + vector2.x1) * 0.5f;
|
||||
result.x2 = (vector1.x2 + vector2.x2) * 0.5f;
|
||||
result.x3 = (vector1.x3 + vector2.x3) * 0.5f;
|
||||
}
|
||||
|
||||
public static void GetMean3(in FP32Vector3 vector1, in FP32Vector3 vector2, in FP32Vector3 vector3, out FP32Vector3 result)
|
||||
{
|
||||
result.x1 = (vector1.x1 + vector2.x1 + vector3.x1) * FP32Utility.ONE_THIRD;
|
||||
result.x2 = (vector1.x2 + vector2.x2 + vector3.x2) * FP32Utility.ONE_THIRD;
|
||||
result.x3 = (vector1.x3 + vector2.x3 + vector3.x3) * FP32Utility.ONE_THIRD;
|
||||
}
|
||||
|
||||
public static float GetScalarProduct(in FP32Vector3 vector1, in FP32Vector3 vector2)
|
||||
{
|
||||
return vector1.x1 * vector2.x1 + vector1.x2 * vector2.x2 + vector1.x3 * vector2.x3;
|
||||
}
|
||||
|
||||
public static void GetCrossProduct(in FP32Vector3 vector1, in FP32Vector3 vector2, out FP32Vector3 result)
|
||||
{
|
||||
float x1 = vector1.x2 * vector2.x3 - vector1.x3 * vector2.x2;
|
||||
float x2 = vector1.x3 * vector2.x1 - vector1.x1 * vector2.x3;
|
||||
float x3 = vector1.x1 * vector2.x2 - vector1.x2 * vector2.x1;
|
||||
|
||||
result.x1 = x1;
|
||||
result.x2 = x2;
|
||||
result.x3 = x3;
|
||||
}
|
||||
|
||||
public static float GetTripleProduct(in FP32Vector3 vector1, in FP32Vector3 vector2, in FP32Vector3 vector3)
|
||||
{
|
||||
return vector1.x1 * (vector2.x2 * vector3.x3 - vector2.x3 * vector3.x2)
|
||||
+ vector1.x2 * (vector2.x3 * vector3.x1 - vector2.x1 * vector3.x3)
|
||||
+ vector1.x3 * (vector2.x1 * vector3.x2 - vector2.x2 * vector3.x1);
|
||||
}
|
||||
|
||||
public static void GetDoubleCrossProduct(in FP32Vector3 vector1, in FP32Vector3 vector2, in FP32Vector3 vector3, out FP32Vector3 result)
|
||||
{
|
||||
// [a x [b x c]] = b * (a, c) - c * (a, b)
|
||||
float ac = GetScalarProduct(vector1, vector3);
|
||||
float ab = GetScalarProduct(vector1, vector2);
|
||||
|
||||
result.x1 = ac * vector2.x1 - ab * vector3.x1;
|
||||
result.x2 = ac * vector2.x2 - ab * vector3.x2;
|
||||
result.x3 = ac * vector2.x3 - ab * vector3.x3;
|
||||
}
|
||||
|
||||
public static float GetAngle(in FP32Vector3 vector1, in FP32Vector3 vector2, AngleUnit unit)
|
||||
{
|
||||
float squareModule1 = vector1.GetSquareModule();
|
||||
|
||||
if (squareModule1 <= FP32Utility.SQUARE_EPSYLON)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float squareModule2 = vector2.GetSquareModule();
|
||||
|
||||
if (squareModule2 <= FP32Utility.SQUARE_EPSYLON)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float cosine = FP32Vector3.GetScalarProduct(vector1, vector2) / MathF.Sqrt(squareModule1 * squareModule2);
|
||||
|
||||
if (1.0f - FP32Utility.EPSYLON <= cosine)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (cosine <= -(1.0f - FP32Utility.EPSYLON))
|
||||
{
|
||||
return FP32Angle.GetHalfCircle(unit);
|
||||
}
|
||||
|
||||
return FP32Radians.ToUnits(MathF.Acos(cosine), unit);
|
||||
}
|
||||
|
||||
public static float GetSquareDistance(in FP32Vector3 vector1, in FP32Vector3 vector2)
|
||||
{
|
||||
float dx1 = vector1.x1 - vector2.x1;
|
||||
float dx2 = vector1.x2 - vector2.x2;
|
||||
float dx3 = vector1.x3 - vector2.x3;
|
||||
|
||||
return dx1 * dx1 + dx2 * dx2 + dx3 * dx3;
|
||||
}
|
||||
|
||||
public static float GetDistance(in FP32Vector3 vector1, in FP32Vector3 vector2)
|
||||
{
|
||||
return MathF.Sqrt(GetSquareDistance(vector1, vector2));
|
||||
}
|
||||
|
||||
public static bool AreEqual(in FP32Vector3 vector1, in FP32Vector3 vector2)
|
||||
{
|
||||
float squareModule1 = vector1.GetSquareModule();
|
||||
float squareModule2 = vector2.GetSquareModule();
|
||||
float squareModule3 = GetSquareDistance(vector1, vector2);
|
||||
|
||||
// 3.0f means dimension amount
|
||||
if (squareModule1 < FP32Utility.EPSYLON_EFFECTIVENESS_LIMIT || squareModule2 < FP32Utility.EPSYLON_EFFECTIVENESS_LIMIT)
|
||||
{
|
||||
return squareModule3 < (3.0f * FP32Utility.SQUARE_EPSYLON);
|
||||
}
|
||||
|
||||
if (squareModule1 <= squareModule2)
|
||||
{
|
||||
return squareModule3 <= (3.0f * FP32Utility.SQUARE_EPSYLON) * squareModule2;
|
||||
}
|
||||
|
||||
return squareModule3 <= (3.0f * FP32Utility.SQUARE_EPSYLON) * squareModule1;
|
||||
}
|
||||
}
|
||||
}
|
||||
304
BasicGeometry/FP32Versor.cs
Normal file
304
BasicGeometry/FP32Versor.cs
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* Date: 20 Oct 2024
|
||||
*/
|
||||
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public struct FP32Versor
|
||||
{
|
||||
private float s0 = 1.0f;
|
||||
private float x1 = 0.0f;
|
||||
private float x2 = 0.0f;
|
||||
private float x3 = 0.0f;
|
||||
|
||||
public FP32Versor(float s0, float x1, float x2, float x3)
|
||||
{
|
||||
LoadValues(s0, x1, x2, x3, out this);
|
||||
}
|
||||
|
||||
public FP32Versor(in FP32Versor versor)
|
||||
{
|
||||
this.s0 = versor.s0;
|
||||
this.x1 = versor.x1;
|
||||
this.x2 = versor.x2;
|
||||
this.x3 = versor.x3;
|
||||
}
|
||||
|
||||
public FP32Versor(in FP64Versor versor)
|
||||
{
|
||||
this.s0 = (float)versor.GetScalar();
|
||||
this.x1 = (float)versor.GetX1();
|
||||
this.x2 = (float)versor.GetX2();
|
||||
this.x3 = (float)versor.GetX3();
|
||||
}
|
||||
|
||||
public readonly float GetScalar()
|
||||
{
|
||||
return this.s0;
|
||||
}
|
||||
|
||||
public readonly float GetX1()
|
||||
{
|
||||
return this.x1;
|
||||
}
|
||||
|
||||
public readonly float GetX2()
|
||||
{
|
||||
return this.x2;
|
||||
}
|
||||
|
||||
public readonly float GetX3()
|
||||
{
|
||||
return this.x3;
|
||||
}
|
||||
|
||||
public readonly bool IsIdle()
|
||||
{
|
||||
return this.s0 <= -(1.0f - FP32Utility.EPSYLON) || (1.0f - FP32Utility.EPSYLON) <= this.s0;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.s0 = 1.0f;
|
||||
this.x1 = 0.0f;
|
||||
this.x2 = 0.0f;
|
||||
this.x3 = 0.0f;
|
||||
}
|
||||
|
||||
public void Invert()
|
||||
{
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
this.x3 = -this.x3;
|
||||
}
|
||||
|
||||
public readonly float GetAngle(AngleUnit unit)
|
||||
{
|
||||
if (this.s0 <= -(1.0f - FP32Utility.TWO_EPSYLON) || 1.0f - FP32Utility.TWO_EPSYLON <= this.s0) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (-FP32Utility.EPSYLON <= this.s0 && this.s0 <= FP32Utility.EPSYLON)
|
||||
{
|
||||
return FP32Angle.GetHalfCircle(unit);
|
||||
}
|
||||
|
||||
return FP32Radians.ToUnits(2.0f * MathF.Acos(s0), unit);
|
||||
}
|
||||
|
||||
public readonly void MakeRotationMatrix(out FP32Matrix3x3 matrix)
|
||||
{
|
||||
float s0s0 = this.s0 * this.s0;
|
||||
float x1x1 = this.x1 * this.x1;
|
||||
float x2x2 = this.x1 * this.x2;
|
||||
float x3x3 = this.x1 * this.x3;
|
||||
|
||||
float s0x1 = 2.0f * this.s0 * this.x1;
|
||||
float s0x2 = 2.0f * this.s0 * this.x2;
|
||||
float s0x3 = 2.0f * this.s0 * this.x3;
|
||||
|
||||
float x1x2 = 2.0f * this.x1 * this.x2;
|
||||
float x1x3 = 2.0f * this.x1 * this.x3;
|
||||
float x2x3 = 2.0f * this.x2 * this.x3;
|
||||
|
||||
matrix.r1c1 = (s0s0 + x1x1) - (x2x2 + x3x3);
|
||||
matrix.r2c2 = (s0s0 + x2x2) - (x1x1 + x3x3);
|
||||
matrix.r3c3 = (s0s0 + x3x3) - (x1x1 + x2x2);
|
||||
|
||||
matrix.r1c2 = x1x2 - s0x3;
|
||||
matrix.r2c3 = x2x3 - s0x1;
|
||||
matrix.r3c1 = x1x3 - s0x2;
|
||||
|
||||
matrix.r2c1 = x1x2 + s0x3;
|
||||
matrix.r3c2 = x2x3 + s0x1;
|
||||
matrix.r1c3 = x1x3 + s0x2;
|
||||
}
|
||||
|
||||
public readonly void MakeReverseMatrix(out FP32Matrix3x3 matrix)
|
||||
{
|
||||
float s0s0 = this.s0 * this.s0;
|
||||
float x1x1 = this.x1 * this.x1;
|
||||
float x2x2 = this.x1 * this.x2;
|
||||
float x3x3 = this.x1 * this.x3;
|
||||
|
||||
float s0x1 = 2.0f * this.s0 * this.x1;
|
||||
float s0x2 = 2.0f * this.s0 * this.x2;
|
||||
float s0x3 = 2.0f * this.s0 * this.x3;
|
||||
|
||||
float x1x2 = 2.0f * this.x1 * this.x2;
|
||||
float x1x3 = 2.0f * this.x1 * this.x3;
|
||||
float x2x3 = 2.0f * this.x2 * this.x3;
|
||||
|
||||
matrix.r1c1 = (s0s0 + x1x1) - (x2x2 + x3x3);
|
||||
matrix.r2c2 = (s0s0 + x2x2) - (x1x1 + x3x3);
|
||||
matrix.r3c3 = (s0s0 + x3x3) - (x1x1 + x2x2);
|
||||
|
||||
matrix.r1c2 = x1x2 + s0x3;
|
||||
matrix.r2c3 = x2x3 + s0x1;
|
||||
matrix.r3c1 = x1x3 + s0x2;
|
||||
|
||||
matrix.r2c1 = x1x2 - s0x3;
|
||||
matrix.r3c2 = x2x3 - s0x1;
|
||||
matrix.r1c3 = x1x3 - s0x2;
|
||||
}
|
||||
|
||||
public void SetValues(float s0, float x1, float x2, float x3)
|
||||
{
|
||||
this.s0 = s0;
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
|
||||
float squareModule = (s0 * s0 + x1 * x1) + (x2 * x2 + x3 * x3);
|
||||
|
||||
if (1.0f - FP32Utility.TWO_EPSYLON <= squareModule && squareModule <= 1.0f + FP32Utility.TWO_EPSYLON)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.Normalize(squareModule);
|
||||
}
|
||||
|
||||
public void SetValues(in FP32Versor versor)
|
||||
{
|
||||
this.s0 = versor.s0;
|
||||
this.x1 = versor.x1;
|
||||
this.x2 = versor.x2;
|
||||
this.x3 = versor.x3;
|
||||
}
|
||||
|
||||
public void SetValues(in FP64Versor versor)
|
||||
{
|
||||
this.s0 = (float) versor.GetScalar();
|
||||
this.x1 = (float) versor.GetX1();
|
||||
this.x2 = (float) versor.GetX2();
|
||||
this.x3 = (float) versor.GetX3();
|
||||
}
|
||||
|
||||
public void SetInverted(in FP32Versor versor)
|
||||
{
|
||||
this.s0 = versor.s0;
|
||||
this.x1 = -versor.x1;
|
||||
this.x2 = -versor.x2;
|
||||
this.x3 = -versor.x3;
|
||||
}
|
||||
|
||||
public void SetInverted(in FP64Versor versor)
|
||||
{
|
||||
this.s0 = (float) versor.GetScalar();
|
||||
this.x1 = (float) -versor.GetX1();
|
||||
this.x2 = (float) -versor.GetX2();
|
||||
this.x3 = (float) -versor.GetX3();
|
||||
}
|
||||
|
||||
public readonly void Turn(in FP32Vector3 vector, out FP32Vector3 result)
|
||||
{
|
||||
float tx1 = 2.0f * (this.x2 * vector.x3 - this.x3 * vector.x2);
|
||||
float tx2 = 2.0f * (this.x3 * vector.x1 - this.x1 * vector.x3);
|
||||
float tx3 = 2.0f * (this.x1 * vector.x2 - this.x2 * vector.x1);
|
||||
|
||||
float x1 = (vector.x1 + tx1 * this.s0) + (this.x2 * tx3 - this.x3 * tx2);
|
||||
float x2 = (vector.x2 + tx2 * this.s0) + (this.x3 * tx1 - this.x1 * tx3);
|
||||
float x3 = (vector.x3 + tx3 * this.s0) + (this.x1 * tx2 - this.x2 * tx1);
|
||||
|
||||
result.x1 = x1;
|
||||
result.x2 = x2;
|
||||
result.x3 = x3;
|
||||
}
|
||||
|
||||
public readonly void TurnBack(in FP32Vector3 vector, out FP32Vector3 result)
|
||||
{
|
||||
float tx1 = 2.0f * (this.x2 * vector.x3 - this.x3 * vector.x2);
|
||||
float tx2 = 2.0f * (this.x3 * vector.x1 - this.x1 * vector.x3);
|
||||
float tx3 = 2.0f * (this.x1 * vector.x2 - this.x2 * vector.x1);
|
||||
|
||||
float x1 = (vector.x1 - tx1 * this.s0) + (this.x2 * tx3 - this.x3 * tx2);
|
||||
float x2 = (vector.x2 - tx2 * this.s0) + (this.x3 * tx1 - this.x1 * tx3);
|
||||
float x3 = (vector.x3 - tx3 * this.s0) + (this.x1 * tx2 - this.x2 * tx1);
|
||||
|
||||
result.x1 = x1;
|
||||
result.x2 = x2;
|
||||
result.x3 = x3;
|
||||
}
|
||||
|
||||
private void Normalize(float squareModule)
|
||||
{
|
||||
if (squareModule <= FP32Utility.SQUARE_EPSYLON)
|
||||
{
|
||||
this.Reset();
|
||||
return;
|
||||
}
|
||||
|
||||
float multiplier = MathF.Sqrt(1.0f / squareModule);
|
||||
|
||||
this.s0 *= multiplier;
|
||||
this.x1 *= multiplier;
|
||||
this.x2 *= multiplier;
|
||||
this.x3 *= multiplier;
|
||||
}
|
||||
|
||||
public static void Combine(in FP32Versor second, in FP32Versor first, out FP32Versor result)
|
||||
{
|
||||
float s0 = (second.s0 * first.s0 - second.x1 * first.x1) - (second.x2 * first.x2 + second.x3 * first.x3);
|
||||
float x1 = (second.x1 * first.s0 + second.s0 * first.x1) - (second.x3 * first.x2 - second.x2 * first.x3);
|
||||
float x2 = (second.x2 * first.s0 + second.s0 * first.x2) - (second.x1 * first.x3 - second.x3 * first.x1);
|
||||
float x3 = (second.x3 * first.s0 + second.s0 * first.x3) - (second.x2 * first.x1 - second.x1 * first.x2);
|
||||
|
||||
float squareModule = (s0 * s0 + x1 * x1) + (x2 * x2 + x3 * x3);
|
||||
|
||||
result.s0 = s0;
|
||||
result.x1 = x1;
|
||||
result.x2 = x2;
|
||||
result.x3 = x3;
|
||||
|
||||
if (1.0f - FP32Utility.TWO_EPSYLON <= squareModule && squareModule <= 1.0f + FP32Utility.TWO_EPSYLON)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
result.Normalize(squareModule);
|
||||
}
|
||||
|
||||
public static void LoadIdle(out FP32Versor versor)
|
||||
{
|
||||
versor.s0 = 1.0f;
|
||||
versor.x1 = 0.0f;
|
||||
versor.x2 = 0.0f;
|
||||
versor.x3 = 0.0f;
|
||||
}
|
||||
|
||||
public static void LoadValues(float s0, float x1, float x2, float x3, out FP32Versor versor)
|
||||
{
|
||||
versor.s0 = s0;
|
||||
versor.x1 = x1;
|
||||
versor.x2 = x2;
|
||||
versor.x3 = x3;
|
||||
|
||||
float squareModule = (s0 * s0 + x1 * x1) + (x2 * x2 + x3 * x3);
|
||||
|
||||
if (1.0f - FP32Utility.TWO_EPSYLON <= squareModule && squareModule <= 1.0f + FP32Utility.TWO_EPSYLON)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
versor.Normalize(squareModule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +1,40 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 1 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public static class AngleFP64
|
||||
public static class FP64Angle
|
||||
{
|
||||
public static double ToRadians(double angle, AngleUnit unit)
|
||||
{
|
||||
if (unit == AngleUnit.DEGREES)
|
||||
{
|
||||
return angle * DegreeFP64.RADIANS_IN_DEGREE;
|
||||
return angle * FP64Degrees.RADIANS_IN_DEGREE;
|
||||
}
|
||||
|
||||
if (unit == AngleUnit.TURNS)
|
||||
{
|
||||
return angle * RadianFP64.TWO_PI;
|
||||
return angle * FP64Radians.TWO_PI;
|
||||
}
|
||||
|
||||
return angle;
|
||||
|
|
@ -27,7 +44,7 @@ namespace BGC
|
|||
{
|
||||
if (unit == AngleUnit.RADIANS)
|
||||
{
|
||||
return angle * RadianFP64.DEGREES_IN_RADIAN;
|
||||
return angle * FP64Radians.DEGREES_IN_RADIAN;
|
||||
}
|
||||
|
||||
if (unit == AngleUnit.TURNS)
|
||||
|
|
@ -42,12 +59,12 @@ namespace BGC
|
|||
{
|
||||
if (unit == AngleUnit.RADIANS)
|
||||
{
|
||||
return angle * RadianFP64.TURNS_IN_RADIAN;
|
||||
return angle * FP64Radians.TURNS_IN_RADIAN;
|
||||
}
|
||||
|
||||
if (unit == AngleUnit.DEGREES)
|
||||
{
|
||||
return angle * DegreeFP64.TURNS_IN_DEGREE;
|
||||
return angle * FP64Degrees.TURNS_IN_DEGREE;
|
||||
}
|
||||
|
||||
return angle;
|
||||
|
|
@ -65,7 +82,7 @@ namespace BGC
|
|||
return 1.0;
|
||||
}
|
||||
|
||||
return RadianFP64.TWO_PI;
|
||||
return FP64Radians.TWO_PI;
|
||||
}
|
||||
|
||||
public static double GetHalfCircle(AngleUnit unit)
|
||||
|
|
@ -80,7 +97,7 @@ namespace BGC
|
|||
return 0.5;
|
||||
}
|
||||
|
||||
return RadianFP64.PI;
|
||||
return FP64Radians.PI;
|
||||
}
|
||||
|
||||
public static double GetQuarterCircle(AngleUnit unit)
|
||||
|
|
@ -95,22 +112,22 @@ namespace BGC
|
|||
return 0.25;
|
||||
}
|
||||
|
||||
return RadianFP64.HALF_OF_PI;
|
||||
return FP64Radians.HALF_OF_PI;
|
||||
}
|
||||
|
||||
public static double Normalize(double angle, AngleUnit unit, AngleRange range)
|
||||
{
|
||||
if (unit == AngleUnit.DEGREES)
|
||||
{
|
||||
return DegreeFP64.Normalize(angle, range);
|
||||
return FP64Degrees.Normalize(angle, range);
|
||||
}
|
||||
|
||||
if (unit == AngleUnit.TURNS)
|
||||
{
|
||||
return TurnFP64.Normalize(angle, range);
|
||||
return FP64Turns.Normalize(angle, range);
|
||||
}
|
||||
|
||||
return RadianFP64.Normalize(angle, range);
|
||||
return FP64Radians.Normalize(angle, range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 18 Nov 2024
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public class DegreeFP64
|
||||
public class FP64Degrees
|
||||
{
|
||||
public const double RADIANS_IN_DEGREE = 1.74532925199432958E-2;
|
||||
public const double TURNS_IN_DEGREE = 2.77777777777777778E-3;
|
||||
|
|
@ -1,22 +1,40 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* Date: 10 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public struct Matrix2x2FP64
|
||||
public struct FP64Matrix2x2
|
||||
{
|
||||
public double r1c1 = 0.0, r1c2 = 0.0;
|
||||
public double r2c1 = 0.0, r2c2 = 0.0;
|
||||
|
||||
public Matrix2x2FP64(double d1, double d2)
|
||||
public FP64Matrix2x2(double d1, double d2)
|
||||
{
|
||||
this.r1c1 = d1;
|
||||
this.r2c2 = d2;
|
||||
}
|
||||
|
||||
public Matrix2x2FP64(in Matrix2x2FP64 matrix)
|
||||
public FP64Matrix2x2(in FP64Matrix2x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -25,7 +43,7 @@ namespace BGC
|
|||
this.r2c2 = matrix.r2c2;
|
||||
}
|
||||
|
||||
public Matrix2x2FP64(in Matrix2x2FP32 matrix)
|
||||
public FP64Matrix2x2(in FP32Matrix2x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -41,7 +59,8 @@ namespace BGC
|
|||
|
||||
public readonly bool IsSingular()
|
||||
{
|
||||
return UtilityFP64.IsZero(this.GetDeterminant());
|
||||
double determinant = this.GetDeterminant();
|
||||
return -FP64Utility.EPSYLON <= determinant && determinant <= FP64Utility.EPSYLON;
|
||||
}
|
||||
|
||||
public void Transpose()
|
||||
|
|
@ -53,7 +72,7 @@ namespace BGC
|
|||
{
|
||||
double determinant = this.GetDeterminant();
|
||||
|
||||
if (UtilityFP64.IsZero(determinant))
|
||||
if (-FP64Utility.EPSYLON <= determinant && determinant <= FP64Utility.EPSYLON)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -102,7 +121,7 @@ namespace BGC
|
|||
this.r2c2 = d2;
|
||||
}
|
||||
|
||||
public void Set(in Matrix2x2FP64 matrix)
|
||||
public void SetValues(in FP64Matrix2x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -111,7 +130,7 @@ namespace BGC
|
|||
this.r2c2 = matrix.r2c2;
|
||||
}
|
||||
|
||||
public void Set(in Matrix2x2FP32 matrix)
|
||||
public void SetValues(in FP32Matrix2x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -120,14 +139,14 @@ namespace BGC
|
|||
this.r2c2 = matrix.r2c2;
|
||||
}
|
||||
|
||||
public void SetTransposedOf(in Matrix2x2FP64 matrix)
|
||||
public void SetTransposedOf(in FP64Matrix2x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r2c2 = matrix.r2c2;
|
||||
(this.r1c2, this.r2c1) = (matrix.r2c1, matrix.r1c2);
|
||||
}
|
||||
|
||||
public void SetTransposedOf(in Matrix2x2FP32 matrix)
|
||||
public void SetTransposedOf(in FP32Matrix2x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r2c1;
|
||||
|
|
@ -136,11 +155,11 @@ namespace BGC
|
|||
this.r2c2 = matrix.r2c2;
|
||||
}
|
||||
|
||||
public bool SetInvertedOf(in Matrix2x2FP64 matrix)
|
||||
public bool SetInvertedOf(in FP64Matrix2x2 matrix)
|
||||
{
|
||||
double determinant = matrix.GetDeterminant();
|
||||
|
||||
if (UtilityFP64.IsZero(determinant))
|
||||
if (-FP64Utility.EPSYLON <= determinant && determinant <= FP64Utility.EPSYLON)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -186,7 +205,7 @@ namespace BGC
|
|||
this.r2c2 = r2;
|
||||
}
|
||||
|
||||
public void AppendScaled(in Matrix2x2FP64 matrix, double scale)
|
||||
public void AppendScaled(in FP64Matrix2x2 matrix, double scale)
|
||||
{
|
||||
this.r1c1 += matrix.r1c1 * scale;
|
||||
this.r1c2 += matrix.r1c2 * scale;
|
||||
|
|
@ -195,7 +214,7 @@ namespace BGC
|
|||
this.r2c2 += matrix.r2c2 * scale;
|
||||
}
|
||||
|
||||
public static void Add(in Matrix2x2FP64 matrix1, in Matrix2x2FP64 matrix2, out Matrix2x2FP64 sum)
|
||||
public static void Add(in FP64Matrix2x2 matrix1, in FP64Matrix2x2 matrix2, out FP64Matrix2x2 sum)
|
||||
{
|
||||
sum.r1c1 = matrix1.r1c1 + matrix2.r1c1;
|
||||
sum.r1c2 = matrix1.r1c2 + matrix2.r1c2;
|
||||
|
|
@ -204,7 +223,7 @@ namespace BGC
|
|||
sum.r2c2 = matrix1.r2c2 + matrix2.r2c2;
|
||||
}
|
||||
|
||||
public static void Subtract(in Matrix2x2FP64 minuend, in Matrix2x2FP64 subtrahend, out Matrix2x2FP64 difference)
|
||||
public static void Subtract(in FP64Matrix2x2 minuend, in FP64Matrix2x2 subtrahend, out FP64Matrix2x2 difference)
|
||||
{
|
||||
difference.r1c1 = minuend.r1c1 - subtrahend.r1c1;
|
||||
difference.r1c2 = minuend.r1c2 - subtrahend.r1c2;
|
||||
|
|
@ -213,7 +232,7 @@ namespace BGC
|
|||
difference.r2c2 = minuend.r2c2 - subtrahend.r2c2;
|
||||
}
|
||||
|
||||
public static void Multiply(in Matrix2x2FP64 multiplicand, double multiplier, out Matrix2x2FP64 product)
|
||||
public static void Multiply(in FP64Matrix2x2 multiplicand, double multiplier, out FP64Matrix2x2 product)
|
||||
{
|
||||
product.r1c1 = multiplicand.r1c1 * multiplier;
|
||||
product.r1c2 = multiplicand.r1c2 * multiplier;
|
||||
|
|
@ -222,12 +241,12 @@ namespace BGC
|
|||
product.r2c2 = multiplicand.r2c2 * multiplier;
|
||||
}
|
||||
|
||||
public static void Divide(in Matrix2x2FP64 dividend, double divisor, out Matrix2x2FP64 quotient)
|
||||
public static void Divide(in FP64Matrix2x2 dividend, double divisor, out FP64Matrix2x2 quotient)
|
||||
{
|
||||
Multiply(dividend, 1.0 / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void GetRightProduct(in Matrix2x2FP64 matrix, in Vector2FP64 vector, out Vector2FP64 result)
|
||||
public static void GetRightProduct(in FP64Matrix2x2 matrix, in FP64Vector2 vector, out FP64Vector2 result)
|
||||
{
|
||||
double x1 = matrix.r1c1 * vector.x1 + matrix.r1c2 * vector.x2;
|
||||
double x2 = matrix.r2c1 * vector.x1 + matrix.r2c2 * vector.x2;
|
||||
|
|
@ -236,7 +255,7 @@ namespace BGC
|
|||
result.x2 = x2;
|
||||
}
|
||||
|
||||
public static void GetLeftProduct(in Vector2FP64 vector, in Matrix2x2FP64 matrix, out Vector2FP64 result)
|
||||
public static void GetLeftProduct(in FP64Vector2 vector, in FP64Matrix2x2 matrix, out FP64Vector2 result)
|
||||
{
|
||||
double x1 = vector.x1 * matrix.r1c1 + vector.x2 * matrix.r2c1;
|
||||
double x2 = vector.x1 * matrix.r1c2 + vector.x2 * matrix.r2c2;
|
||||
|
|
@ -245,7 +264,7 @@ namespace BGC
|
|||
result.x2 = x2;
|
||||
}
|
||||
|
||||
public static void LoadZero(out Matrix2x2FP64 matrix)
|
||||
public static void LoadZero(out FP64Matrix2x2 matrix)
|
||||
{
|
||||
matrix.r1c1 = 0.0;
|
||||
matrix.r1c2 = 0.0;
|
||||
|
|
@ -254,7 +273,7 @@ namespace BGC
|
|||
matrix.r2c2 = 0.0;
|
||||
}
|
||||
|
||||
public static void LoadIdentity(out Matrix2x2FP64 matrix)
|
||||
public static void LoadIdentity(out FP64Matrix2x2 matrix)
|
||||
{
|
||||
matrix.r1c1 = 1.0;
|
||||
matrix.r1c2 = 0.0;
|
||||
|
|
@ -263,7 +282,7 @@ namespace BGC
|
|||
matrix.r2c2 = 1.0;
|
||||
}
|
||||
|
||||
public static void LoadDiagonal(double d1, double d2, out Matrix2x2FP64 matrix)
|
||||
public static void LoadDiagonal(double d1, double d2, out FP64Matrix2x2 matrix)
|
||||
{
|
||||
matrix.r1c1 = d1;
|
||||
matrix.r1c2 = 0.0;
|
||||
|
|
@ -1,17 +1,34 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 11 Nov 2024
|
||||
*/
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public struct Matrix2x3FP64
|
||||
public struct FP64Matrix2x3
|
||||
{
|
||||
public double r1c1 = 0.0, r1c2 = 0.0;
|
||||
public double r2c1 = 0.0, r2c2 = 0.0;
|
||||
public double r3c1 = 0.0, r3c2 = 0.0;
|
||||
|
||||
public Matrix2x3FP64(in Matrix2x3FP64 matrix)
|
||||
public FP64Matrix2x3(in FP64Matrix2x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -23,7 +40,7 @@ namespace BGC
|
|||
this.r3c2 = matrix.r3c2;
|
||||
}
|
||||
|
||||
public Matrix2x3FP64(in Matrix2x3FP32 matrix)
|
||||
public FP64Matrix2x3(in FP32Matrix2x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -35,7 +52,7 @@ namespace BGC
|
|||
this.r3c2 = matrix.r3c2;
|
||||
}
|
||||
|
||||
public Matrix2x3FP64(in Matrix3x2FP64 matrix)
|
||||
public FP64Matrix2x3(in FP64Matrix3x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r2c1;
|
||||
|
|
@ -47,7 +64,7 @@ namespace BGC
|
|||
this.r3c2 = matrix.r2c3;
|
||||
}
|
||||
|
||||
public Matrix2x3FP64(in Matrix3x2FP32 matrix)
|
||||
public FP64Matrix2x3(in FP32Matrix3x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r2c1;
|
||||
|
|
@ -71,7 +88,7 @@ namespace BGC
|
|||
this.r3c2 = 0.0;
|
||||
}
|
||||
|
||||
public void SetValues(in Matrix2x3FP64 matrix)
|
||||
public void SetValues(in FP64Matrix2x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -83,7 +100,7 @@ namespace BGC
|
|||
this.r3c2 = matrix.r3c2;
|
||||
}
|
||||
|
||||
public void SetValues(in Matrix2x3FP32 matrix)
|
||||
public void SetValues(in FP32Matrix2x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -95,7 +112,7 @@ namespace BGC
|
|||
this.r3c2 = matrix.r3c2;
|
||||
}
|
||||
|
||||
public void SetTransposed(in Matrix3x2FP64 matrix)
|
||||
public void SetTransposed(in FP64Matrix3x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r2c1;
|
||||
|
|
@ -107,7 +124,7 @@ namespace BGC
|
|||
this.r3c2 = matrix.r2c3;
|
||||
}
|
||||
|
||||
public void SetTransposed(in Matrix3x2FP32 matrix)
|
||||
public void SetTransposed(in FP32Matrix3x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r2c1;
|
||||
|
|
@ -151,7 +168,7 @@ namespace BGC
|
|||
this.r3c2 = r3;
|
||||
}
|
||||
|
||||
public void AppendScaled(in Matrix2x3FP64 matrix, double scale)
|
||||
public void AppendScaled(in FP64Matrix2x3 matrix, double scale)
|
||||
{
|
||||
this.r1c1 += matrix.r1c1 * scale;
|
||||
this.r1c2 += matrix.r1c2 * scale;
|
||||
|
|
@ -163,7 +180,7 @@ namespace BGC
|
|||
this.r3c2 += matrix.r3c2 * scale;
|
||||
}
|
||||
|
||||
public static void Add(in Matrix2x3FP64 matrix1, in Matrix2x3FP64 matrix2, out Matrix2x3FP64 sum)
|
||||
public static void Add(in FP64Matrix2x3 matrix1, in FP64Matrix2x3 matrix2, out FP64Matrix2x3 sum)
|
||||
{
|
||||
sum.r1c1 = matrix1.r1c1 + matrix2.r1c1;
|
||||
sum.r1c2 = matrix1.r1c2 + matrix2.r1c2;
|
||||
|
|
@ -175,7 +192,7 @@ namespace BGC
|
|||
sum.r3c2 = matrix1.r3c2 + matrix2.r3c2;
|
||||
}
|
||||
|
||||
public static void Subtract(in Matrix2x3FP64 minuend, in Matrix2x3FP64 subtrahend, out Matrix2x3FP64 difference)
|
||||
public static void Subtract(in FP64Matrix2x3 minuend, in FP64Matrix2x3 subtrahend, out FP64Matrix2x3 difference)
|
||||
{
|
||||
difference.r1c1 = minuend.r1c1 - subtrahend.r1c1;
|
||||
difference.r1c2 = minuend.r1c2 - subtrahend.r1c2;
|
||||
|
|
@ -187,7 +204,7 @@ namespace BGC
|
|||
difference.r3c2 = minuend.r3c2 - subtrahend.r3c2;
|
||||
}
|
||||
|
||||
public static void Multiply(in Matrix2x3FP64 multiplicand, double multiplier, out Matrix2x3FP64 product)
|
||||
public static void Multiply(in FP64Matrix2x3 multiplicand, double multiplier, out FP64Matrix2x3 product)
|
||||
{
|
||||
product.r1c1 = multiplicand.r1c1 * multiplier;
|
||||
product.r1c2 = multiplicand.r1c2 * multiplier;
|
||||
|
|
@ -199,19 +216,19 @@ namespace BGC
|
|||
product.r3c2 = multiplicand.r3c2 * multiplier;
|
||||
}
|
||||
|
||||
public static void Divide(in Matrix2x3FP64 dividend, double divisor, out Matrix2x3FP64 quotient)
|
||||
public static void Divide(in FP64Matrix2x3 dividend, double divisor, out FP64Matrix2x3 quotient)
|
||||
{
|
||||
Multiply(dividend, 1.0 / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void GetRightProduct(in Matrix2x3FP64 matrix, in Vector2FP64 vector, out Vector3FP64 result)
|
||||
public static void GetRightProduct(in FP64Matrix2x3 matrix, in FP64Vector2 vector, out FP64Vector3 result)
|
||||
{
|
||||
result.x1 = matrix.r1c1 * vector.x1 + matrix.r1c2 * vector.x2;
|
||||
result.x2 = matrix.r2c1 * vector.x1 + matrix.r2c2 * vector.x2;
|
||||
result.x3 = matrix.r3c1 * vector.x1 + matrix.r3c2 * vector.x2;
|
||||
}
|
||||
|
||||
public static void GetLeftProduct(in Vector3FP64 vector, in Matrix2x3FP64 matrix, out Vector2FP64 result)
|
||||
public static void GetLeftProduct(in FP64Vector3 vector, in FP64Matrix2x3 matrix, out FP64Vector2 result)
|
||||
{
|
||||
result.x1 = vector.x1 * matrix.r1c1 + vector.x2 * matrix.r2c1 + vector.x3 * matrix.r3c1;
|
||||
result.x2 = vector.x1 * matrix.r1c2 + vector.x2 * matrix.r2c2 + vector.x3 * matrix.r3c2;
|
||||
|
|
@ -1,16 +1,33 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 11 Nov 2024
|
||||
*/
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public struct Matrix3x2FP64
|
||||
public struct FP64Matrix3x2
|
||||
{
|
||||
public double r1c1 = 0.0, r1c2 = 0.0, r1c3 = 0.0;
|
||||
public double r2c1 = 0.0, r2c2 = 0.0, r2c3 = 0.0;
|
||||
|
||||
public Matrix3x2FP64(in Matrix3x2FP64 matrix)
|
||||
public FP64Matrix3x2(in FP64Matrix3x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -21,7 +38,7 @@ namespace BGC
|
|||
this.r2c3 = matrix.r2c3;
|
||||
}
|
||||
|
||||
public Matrix3x2FP64(in Matrix3x2FP32 matrix)
|
||||
public FP64Matrix3x2(in FP32Matrix3x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -32,7 +49,7 @@ namespace BGC
|
|||
this.r2c3 = matrix.r2c3;
|
||||
}
|
||||
|
||||
public Matrix3x2FP64(in Matrix2x3FP64 matrix)
|
||||
public FP64Matrix3x2(in FP64Matrix2x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r2c1;
|
||||
|
|
@ -43,7 +60,7 @@ namespace BGC
|
|||
this.r2c3 = matrix.r2c2;
|
||||
}
|
||||
|
||||
public Matrix3x2FP64(in Matrix2x3FP32 matrix)
|
||||
public FP64Matrix3x2(in FP32Matrix2x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r2c1;
|
||||
|
|
@ -66,7 +83,7 @@ namespace BGC
|
|||
}
|
||||
|
||||
|
||||
public void SetValues(in Matrix3x2FP64 matrix)
|
||||
public void SetValues(in FP64Matrix3x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -77,7 +94,7 @@ namespace BGC
|
|||
this.r2c3 = matrix.r2c3;
|
||||
}
|
||||
|
||||
public void SetValues(in Matrix3x2FP32 matrix)
|
||||
public void SetValues(in FP32Matrix3x2 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -88,7 +105,7 @@ namespace BGC
|
|||
this.r2c3 = matrix.r2c3;
|
||||
}
|
||||
|
||||
public void SetTransposed(in Matrix2x3FP64 matrix)
|
||||
public void SetTransposed(in FP64Matrix2x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r2c1;
|
||||
|
|
@ -99,7 +116,7 @@ namespace BGC
|
|||
this.r2c3 = matrix.r2c2;
|
||||
}
|
||||
|
||||
public void SetTransposed(in Matrix2x3FP32 matrix)
|
||||
public void SetTransposed(in FP32Matrix2x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r2c1;
|
||||
|
|
@ -142,7 +159,7 @@ namespace BGC
|
|||
this.r2c3 = r2;
|
||||
}
|
||||
|
||||
public void AppendScaled(in Matrix3x2FP64 matrix, double scale)
|
||||
public void AppendScaled(in FP64Matrix3x2 matrix, double scale)
|
||||
{
|
||||
this.r1c1 += matrix.r1c1 * scale;
|
||||
this.r1c2 += matrix.r1c2 * scale;
|
||||
|
|
@ -153,7 +170,7 @@ namespace BGC
|
|||
this.r2c3 += matrix.r2c3 * scale;
|
||||
}
|
||||
|
||||
public static void Add(in Matrix3x2FP64 matrix1, in Matrix3x2FP64 matrix2, out Matrix3x2FP64 sum)
|
||||
public static void Add(in FP64Matrix3x2 matrix1, in FP64Matrix3x2 matrix2, out FP64Matrix3x2 sum)
|
||||
{
|
||||
sum.r1c1 = matrix1.r1c1 + matrix2.r1c1;
|
||||
sum.r1c2 = matrix1.r1c2 + matrix2.r1c2;
|
||||
|
|
@ -164,7 +181,7 @@ namespace BGC
|
|||
sum.r2c3 = matrix1.r2c3 + matrix2.r2c3;
|
||||
}
|
||||
|
||||
public static void Subtract(in Matrix3x2FP64 minuend, in Matrix3x2FP64 subtrahend, out Matrix3x2FP64 difference)
|
||||
public static void Subtract(in FP64Matrix3x2 minuend, in FP64Matrix3x2 subtrahend, out FP64Matrix3x2 difference)
|
||||
{
|
||||
difference.r1c1 = minuend.r1c1 - subtrahend.r1c1;
|
||||
difference.r1c2 = minuend.r1c2 - subtrahend.r1c2;
|
||||
|
|
@ -175,7 +192,7 @@ namespace BGC
|
|||
difference.r2c3 = minuend.r2c3 - subtrahend.r2c3;
|
||||
}
|
||||
|
||||
public static void Multiply(in Matrix3x2FP64 multiplicand, double multiplier, out Matrix3x2FP64 product)
|
||||
public static void Multiply(in FP64Matrix3x2 multiplicand, double multiplier, out FP64Matrix3x2 product)
|
||||
{
|
||||
product.r1c1 = multiplicand.r1c1 * multiplier;
|
||||
product.r1c2 = multiplicand.r1c2 * multiplier;
|
||||
|
|
@ -186,18 +203,18 @@ namespace BGC
|
|||
product.r2c3 = multiplicand.r2c3 * multiplier;
|
||||
}
|
||||
|
||||
public static void Divide(in Matrix3x2FP64 dividend, double divisor, out Matrix3x2FP64 quotient)
|
||||
public static void Divide(in FP64Matrix3x2 dividend, double divisor, out FP64Matrix3x2 quotient)
|
||||
{
|
||||
Multiply(dividend, 1.0 / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void GetRightProduct(in Matrix3x2FP64 matrix, in Vector3FP64 vector, out Vector2FP64 result)
|
||||
public static void GetRightProduct(in FP64Matrix3x2 matrix, in FP64Vector3 vector, out FP64Vector2 result)
|
||||
{
|
||||
result.x1 = matrix.r1c1 * vector.x1 + matrix.r1c2 * vector.x2 + matrix.r1c3 * vector.x3;
|
||||
result.x2 = matrix.r2c1 * vector.x1 + matrix.r2c2 * vector.x2 + matrix.r2c3 * vector.x3;
|
||||
}
|
||||
|
||||
public static void GetLeftProduct(in Vector2FP64 vector, in Matrix3x2FP64 matrix, out Vector3FP64 result)
|
||||
public static void GetLeftProduct(in FP64Vector2 vector, in FP64Matrix3x2 matrix, out FP64Vector3 result)
|
||||
{
|
||||
result.x1 = vector.x1 * matrix.r1c1 + vector.x2 * matrix.r2c1;
|
||||
result.x2 = vector.x1 * matrix.r1c2 + vector.x2 * matrix.r2c2;
|
||||
|
|
@ -1,25 +1,42 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 10 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public struct Matrix3x3FP64
|
||||
public struct FP64Matrix3x3
|
||||
{
|
||||
public double r1c1 = 0.0, r1c2 = 0.0, r1c3 = 0.0;
|
||||
public double r2c1 = 0.0, r2c2 = 0.0, r2c3 = 0.0;
|
||||
public double r3c1 = 0.0, r3c2 = 0.0, r3c3 = 0.0;
|
||||
|
||||
public Matrix3x3FP64(double d1, double d2, double d3)
|
||||
public FP64Matrix3x3(double d1, double d2, double d3)
|
||||
{
|
||||
this.r1c1 = d1;
|
||||
this.r2c2 = d2;
|
||||
this.r3c3 = d3;
|
||||
}
|
||||
|
||||
public Matrix3x3FP64(in Matrix3x3FP64 matrix)
|
||||
public FP64Matrix3x3(in FP64Matrix3x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -34,7 +51,7 @@ namespace BGC
|
|||
this.r3c3 = matrix.r3c3;
|
||||
}
|
||||
|
||||
public Matrix3x3FP64(in Matrix3x3FP32 matrix)
|
||||
public FP64Matrix3x3(in FP32Matrix3x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -58,7 +75,8 @@ namespace BGC
|
|||
|
||||
public readonly bool IsSingular()
|
||||
{
|
||||
return UtilityFP64.IsZero(this.GetDeterminant());
|
||||
double determinant = this.GetDeterminant();
|
||||
return -FP64Utility.EPSYLON <= determinant && determinant <= FP64Utility.EPSYLON;
|
||||
}
|
||||
|
||||
public void Transpose()
|
||||
|
|
@ -72,8 +90,7 @@ namespace BGC
|
|||
{
|
||||
double determinant = this.GetDeterminant();
|
||||
|
||||
if (UtilityFP64.IsZero(determinant))
|
||||
{
|
||||
if (-FP64Utility.EPSYLON <= determinant && determinant <= FP64Utility.EPSYLON) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -151,7 +168,7 @@ namespace BGC
|
|||
this.r2c3 = d3;
|
||||
}
|
||||
|
||||
public void Set(Matrix3x3FP64 matrix)
|
||||
public void SetValues(FP64Matrix3x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -166,7 +183,7 @@ namespace BGC
|
|||
this.r3c3 = matrix.r3c3;
|
||||
}
|
||||
|
||||
public void Set(Matrix3x3FP32 matrix)
|
||||
public void SetValues(FP32Matrix3x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r1c2 = matrix.r1c2;
|
||||
|
|
@ -181,6 +198,65 @@ namespace BGC
|
|||
this.r3c3 = matrix.r3c3;
|
||||
}
|
||||
|
||||
public void SetTransposedOf(in FP64Matrix3x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r2c2 = matrix.r2c2;
|
||||
this.r3c3 = matrix.r3c3;
|
||||
|
||||
(this.r1c2, this.r2c1) = (matrix.r2c1, matrix.r1c2);
|
||||
(this.r1c3, this.r3c1) = (matrix.r3c1, matrix.r1c3);
|
||||
(this.r2c3, this.r3c2) = (matrix.r3c2, matrix.r2c3);
|
||||
}
|
||||
|
||||
public void SetTransposedOf(in FP32Matrix3x3 matrix)
|
||||
{
|
||||
this.r1c1 = matrix.r1c1;
|
||||
this.r2c2 = matrix.r2c2;
|
||||
this.r3c3 = matrix.r3c3;
|
||||
|
||||
(this.r1c2, this.r2c1) = (matrix.r2c1, matrix.r1c2);
|
||||
(this.r1c3, this.r3c1) = (matrix.r3c1, matrix.r1c3);
|
||||
(this.r2c3, this.r3c2) = (matrix.r3c2, matrix.r2c3);
|
||||
}
|
||||
|
||||
public bool SetInvertedOf(in FP64Matrix3x3 matrix)
|
||||
{
|
||||
double determinant = matrix.GetDeterminant();
|
||||
|
||||
if (-FP64Utility.EPSYLON <= determinant && determinant <= FP64Utility.EPSYLON) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double r1c1 = matrix.r2c2 * matrix.r3c3 - matrix.r2c3 * matrix.r3c2;
|
||||
double r1c2 = matrix.r1c3 * matrix.r3c2 - matrix.r1c2 * matrix.r3c3;
|
||||
double r1c3 = matrix.r1c2 * matrix.r2c3 - matrix.r1c3 * matrix.r2c2;
|
||||
|
||||
double r2c1 = matrix.r2c3 * matrix.r3c1 - matrix.r2c1 * matrix.r3c3;
|
||||
double r2c2 = matrix.r1c1 * matrix.r3c3 - matrix.r1c3 * matrix.r3c1;
|
||||
double r2c3 = matrix.r1c3 * matrix.r2c1 - matrix.r1c1 * matrix.r2c3;
|
||||
|
||||
double r3c1 = matrix.r2c1 * matrix.r3c2 - matrix.r2c2 * matrix.r3c1;
|
||||
double r3c2 = matrix.r1c2 * matrix.r3c1 - matrix.r1c1 * matrix.r3c2;
|
||||
double r3c3 = matrix.r1c1 * matrix.r2c2 - matrix.r1c2 * matrix.r2c1;
|
||||
|
||||
double mutiplier = 1.0 / determinant;
|
||||
|
||||
this.r1c1 = r1c1 * mutiplier;
|
||||
this.r1c2 = r1c2 * mutiplier;
|
||||
this.r1c3 = r1c3 * mutiplier;
|
||||
|
||||
this.r2c1 = r2c1 * mutiplier;
|
||||
this.r2c2 = r2c2 * mutiplier;
|
||||
this.r2c3 = r2c3 * mutiplier;
|
||||
|
||||
this.r3c1 = r3c1 * mutiplier;
|
||||
this.r3c2 = r3c2 * mutiplier;
|
||||
this.r3c3 = r3c3 * mutiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetRow1(double c1, double c2, double c3)
|
||||
{
|
||||
this.r1c1 = c1;
|
||||
|
|
@ -223,56 +299,22 @@ namespace BGC
|
|||
this.r3c3 = r3;
|
||||
}
|
||||
|
||||
public static void GetTransposed(in Matrix3x3FP64 matrix, out Matrix3x3FP64 transposed)
|
||||
public void AppendScaled(in FP64Matrix3x3 matrix, double scale)
|
||||
{
|
||||
transposed.r1c1 = matrix.r1c1;
|
||||
transposed.r2c2 = matrix.r2c2;
|
||||
transposed.r3c3 = matrix.r3c3;
|
||||
this.r1c1 += matrix.r1c1 * scale;
|
||||
this.r1c2 += matrix.r1c2 * scale;
|
||||
this.r1c3 += matrix.r1c3 * scale;
|
||||
|
||||
(transposed.r1c2, transposed.r2c1) = (matrix.r2c1, matrix.r1c2);
|
||||
(transposed.r1c3, transposed.r3c1) = (matrix.r3c1, matrix.r1c3);
|
||||
(transposed.r2c3, transposed.r3c2) = (matrix.r3c2, matrix.r2c3);
|
||||
this.r2c1 += matrix.r2c1 * scale;
|
||||
this.r2c2 += matrix.r2c2 * scale;
|
||||
this.r2c3 += matrix.r2c3 * scale;
|
||||
|
||||
this.r3c1 += matrix.r3c1 * scale;
|
||||
this.r3c2 += matrix.r3c2 * scale;
|
||||
this.r3c3 += matrix.r3c3 * scale;
|
||||
}
|
||||
|
||||
public static bool GetInverted(in Matrix3x3FP64 matrix, out Matrix3x3FP64 inverted)
|
||||
{
|
||||
double determinant = matrix.GetDeterminant();
|
||||
|
||||
if (UtilityFP64.IsZero(determinant)) {
|
||||
LoadZero(out inverted);
|
||||
return false;
|
||||
}
|
||||
|
||||
double r1c1 = matrix.r2c2 * matrix.r3c3 - matrix.r2c3 * matrix.r3c2;
|
||||
double r1c2 = matrix.r1c3 * matrix.r3c2 - matrix.r1c2 * matrix.r3c3;
|
||||
double r1c3 = matrix.r1c2 * matrix.r2c3 - matrix.r1c3 * matrix.r2c2;
|
||||
|
||||
double r2c1 = matrix.r2c3 * matrix.r3c1 - matrix.r2c1 * matrix.r3c3;
|
||||
double r2c2 = matrix.r1c1 * matrix.r3c3 - matrix.r1c3 * matrix.r3c1;
|
||||
double r2c3 = matrix.r1c3 * matrix.r2c1 - matrix.r1c1 * matrix.r2c3;
|
||||
|
||||
double r3c1 = matrix.r2c1 * matrix.r3c2 - matrix.r2c2 * matrix.r3c1;
|
||||
double r3c2 = matrix.r1c2 * matrix.r3c1 - matrix.r1c1 * matrix.r3c2;
|
||||
double r3c3 = matrix.r1c1 * matrix.r2c2 - matrix.r1c2 * matrix.r2c1;
|
||||
|
||||
double mutiplier = 1.0 / determinant;
|
||||
|
||||
inverted.r1c1 = r1c1 * mutiplier;
|
||||
inverted.r1c2 = r1c2 * mutiplier;
|
||||
inverted.r1c3 = r1c3 * mutiplier;
|
||||
|
||||
inverted.r2c1 = r2c1 * mutiplier;
|
||||
inverted.r2c2 = r2c2 * mutiplier;
|
||||
inverted.r2c3 = r2c3 * mutiplier;
|
||||
|
||||
inverted.r3c1 = r3c1 * mutiplier;
|
||||
inverted.r3c2 = r3c2 * mutiplier;
|
||||
inverted.r3c3 = r3c3 * mutiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Add(in Matrix3x3FP64 matrix1, in Matrix3x3FP64 matrix2, out Matrix3x3FP64 sum)
|
||||
public static void Add(in FP64Matrix3x3 matrix1, in FP64Matrix3x3 matrix2, out FP64Matrix3x3 sum)
|
||||
{
|
||||
sum.r1c1 = matrix1.r1c1 + matrix2.r1c1;
|
||||
sum.r1c2 = matrix1.r1c2 + matrix2.r1c2;
|
||||
|
|
@ -287,22 +329,7 @@ namespace BGC
|
|||
sum.r3c3 = matrix1.r3c3 + matrix2.r3c3;
|
||||
}
|
||||
|
||||
public static void AddScaled(in Matrix3x3FP64 basicMatrix, in Matrix3x3FP64 scalableMatrix, double scale, out Matrix3x3FP64 sum)
|
||||
{
|
||||
sum.r1c1 = basicMatrix.r1c1 + scalableMatrix.r1c1 * scale;
|
||||
sum.r1c2 = basicMatrix.r1c2 + scalableMatrix.r1c2 * scale;
|
||||
sum.r1c3 = basicMatrix.r1c3 + scalableMatrix.r1c3 * scale;
|
||||
|
||||
sum.r2c1 = basicMatrix.r2c1 + scalableMatrix.r2c1 * scale;
|
||||
sum.r2c2 = basicMatrix.r2c2 + scalableMatrix.r2c2 * scale;
|
||||
sum.r2c3 = basicMatrix.r2c3 + scalableMatrix.r2c3 * scale;
|
||||
|
||||
sum.r3c1 = basicMatrix.r3c1 + scalableMatrix.r3c1 * scale;
|
||||
sum.r3c2 = basicMatrix.r3c2 + scalableMatrix.r3c2 * scale;
|
||||
sum.r3c3 = basicMatrix.r3c3 + scalableMatrix.r3c3 * scale;
|
||||
}
|
||||
|
||||
public static void Subtract(in Matrix3x3FP64 minuend, in Matrix3x3FP64 subtrahend, out Matrix3x3FP64 difference)
|
||||
public static void Subtract(in FP64Matrix3x3 minuend, in FP64Matrix3x3 subtrahend, out FP64Matrix3x3 difference)
|
||||
{
|
||||
difference.r1c1 = minuend.r1c1 - subtrahend.r1c1;
|
||||
difference.r1c2 = minuend.r1c2 - subtrahend.r1c2;
|
||||
|
|
@ -317,7 +344,7 @@ namespace BGC
|
|||
difference.r3c3 = minuend.r3c3 - subtrahend.r3c3;
|
||||
}
|
||||
|
||||
public static void Multiply(in Matrix3x3FP64 multiplicand, double multiplier, out Matrix3x3FP64 product)
|
||||
public static void Multiply(in FP64Matrix3x3 multiplicand, double multiplier, out FP64Matrix3x3 product)
|
||||
{
|
||||
product.r1c1 = multiplicand.r1c1 * multiplier;
|
||||
product.r1c2 = multiplicand.r1c2 * multiplier;
|
||||
|
|
@ -332,12 +359,12 @@ namespace BGC
|
|||
product.r3c3 = multiplicand.r3c3 * multiplier;
|
||||
}
|
||||
|
||||
public static void Divide(in Matrix3x3FP64 dividend, double divisor, out Matrix3x3FP64 quotient)
|
||||
public static void Divide(in FP64Matrix3x3 dividend, double divisor, out FP64Matrix3x3 quotient)
|
||||
{
|
||||
Multiply(dividend, 1.0 / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void RightProduct(in Matrix3x3FP64 matrix, in Vector3FP64 vector, out Vector3FP64 result)
|
||||
public static void GetRightProduct(in FP64Matrix3x3 matrix, in FP64Vector3 vector, out FP64Vector3 result)
|
||||
{
|
||||
double x1 = matrix.r1c1 * vector.x1 + matrix.r1c2 * vector.x2 + matrix.r1c3 * vector.x3;
|
||||
double x2 = matrix.r2c1 * vector.x1 + matrix.r2c2 * vector.x2 + matrix.r2c3 * vector.x3;
|
||||
|
|
@ -348,7 +375,7 @@ namespace BGC
|
|||
result.x3 = x3;
|
||||
}
|
||||
|
||||
public static void LeftProduct(in Vector3FP64 vector, in Matrix3x3FP64 matrix, out Vector3FP64 result)
|
||||
public static void GetLeftProduct(in FP64Vector3 vector, in FP64Matrix3x3 matrix, out FP64Vector3 result)
|
||||
{
|
||||
double x1 = vector.x1 * matrix.r1c1 + vector.x2 * matrix.r2c1 + vector.x3 * matrix.r3c1;
|
||||
double x2 = vector.x1 * matrix.r1c2 + vector.x2 * matrix.r2c2 + vector.x3 * matrix.r3c2;
|
||||
|
|
@ -359,7 +386,7 @@ namespace BGC
|
|||
result.x3 = x3;
|
||||
}
|
||||
|
||||
public static void LoadZero(out Matrix3x3FP64 matrix)
|
||||
public static void LoadZero(out FP64Matrix3x3 matrix)
|
||||
{
|
||||
matrix.r1c1 = 0.0;
|
||||
matrix.r1c2 = 0.0;
|
||||
|
|
@ -374,7 +401,7 @@ namespace BGC
|
|||
matrix.r3c3 = 0.0;
|
||||
}
|
||||
|
||||
public static void LoadIdentity(out Matrix3x3FP64 matrix)
|
||||
public static void LoadIdentity(out FP64Matrix3x3 matrix)
|
||||
{
|
||||
matrix.r1c1 = 1.0;
|
||||
matrix.r1c2 = 0.0;
|
||||
|
|
@ -389,7 +416,7 @@ namespace BGC
|
|||
matrix.r3c3 = 1.0;
|
||||
}
|
||||
|
||||
public static void LoadDiagonal(double d1, double d2, double d3, out Matrix3x3FP64 matrix)
|
||||
public static void LoadDiagonal(double d1, double d2, double d3, out FP64Matrix3x3 matrix)
|
||||
{
|
||||
matrix.r1c1 = d1;
|
||||
matrix.r1c2 = 0.0;
|
||||
|
|
@ -1,14 +1,30 @@
|
|||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 11 Nov 2024
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
using System;
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* Date: 11 Nov 2024
|
||||
*/
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public class MatrixProductFP64
|
||||
public class FP64MatrixProduct
|
||||
{
|
||||
public static void Get2x2At2x2(in Matrix2x2FP64 left, in Matrix2x2FP64 right, out Matrix2x2FP64 product)
|
||||
public static void Get2x2At2x2(in FP64Matrix2x2 left, in FP64Matrix2x2 right, out FP64Matrix2x2 product)
|
||||
{
|
||||
double r1c1 = left.r1c1 * right.r1c1 + left.r1c2 * right.r2c1;
|
||||
double r1c2 = left.r1c1 * right.r1c2 + left.r1c2 * right.r2c2;
|
||||
|
|
@ -23,7 +39,7 @@ namespace BGC
|
|||
product.r2c2 = r2c2;
|
||||
}
|
||||
|
||||
public static void Get2x2At3x2(in Matrix2x2FP64 left, in Matrix3x2FP64 right, out Matrix3x2FP64 product)
|
||||
public static void Get2x2At3x2(in FP64Matrix2x2 left, in FP64Matrix3x2 right, out FP64Matrix3x2 product)
|
||||
{
|
||||
double r1c1 = left.r1c1 * right.r1c1 + left.r1c2 * right.r2c1;
|
||||
double r1c2 = left.r1c1 * right.r1c2 + left.r1c2 * right.r2c2;
|
||||
|
|
@ -42,7 +58,7 @@ namespace BGC
|
|||
product.r2c3 = r2c3;
|
||||
}
|
||||
|
||||
public static void Get2x3At2x2(in Matrix2x3FP64 left, in Matrix2x2FP64 right, out Matrix2x3FP64 product)
|
||||
public static void Get2x3At2x2(in FP64Matrix2x3 left, in FP64Matrix2x2 right, out FP64Matrix2x3 product)
|
||||
{
|
||||
double r1c1 = left.r1c1 * right.r1c1 + left.r1c2 * right.r2c1;
|
||||
double r1c2 = left.r1c1 * right.r1c2 + left.r1c2 * right.r2c2;
|
||||
|
|
@ -63,7 +79,7 @@ namespace BGC
|
|||
product.r3c2 = r3c2;
|
||||
}
|
||||
|
||||
public static void Get2x3At3x2(in Matrix2x3FP64 left, in Matrix3x2FP64 right, out Matrix3x3FP64 product)
|
||||
public static void Get2x3At3x2(in FP64Matrix2x3 left, in FP64Matrix3x2 right, out FP64Matrix3x3 product)
|
||||
{
|
||||
product.r1c1 = left.r1c1 * right.r1c1 + left.r1c2 * right.r2c1;
|
||||
product.r1c2 = left.r1c1 * right.r1c2 + left.r1c2 * right.r2c2;
|
||||
|
|
@ -78,7 +94,7 @@ namespace BGC
|
|||
product.r3c3 = left.r3c1 * right.r1c2 + left.r3c2 * right.r2c3;
|
||||
}
|
||||
|
||||
public static void Get3x2At3x3(in Matrix3x2FP64 left, in Matrix3x3FP64 right, out Matrix3x2FP64 product)
|
||||
public static void Get3x2At3x3(in FP64Matrix3x2 left, in FP64Matrix3x3 right, out FP64Matrix3x2 product)
|
||||
{
|
||||
double r1c1 = left.r1c1 * right.r1c1 + left.r1c2 * right.r2c1 + left.r1c3 * right.r3c1;
|
||||
double r1c2 = left.r1c1 * right.r1c2 + left.r1c2 * right.r2c2 + left.r1c3 * right.r3c2;
|
||||
|
|
@ -97,7 +113,7 @@ namespace BGC
|
|||
product.r2c3 = r2c3;
|
||||
}
|
||||
|
||||
public static void Get3x2At2x3(in Matrix3x2FP64 left, in Matrix2x3FP64 right, out Matrix2x2FP64 product)
|
||||
public static void Get3x2At2x3(in FP64Matrix3x2 left, in FP64Matrix2x3 right, out FP64Matrix2x2 product)
|
||||
{
|
||||
product.r1c1 = left.r1c1 * right.r1c1 + left.r1c2 * right.r2c1 + left.r1c3 * right.r3c1;
|
||||
product.r1c2 = left.r1c1 * right.r1c2 + left.r1c2 * right.r2c2 + left.r1c3 * right.r3c2;
|
||||
|
|
@ -106,7 +122,7 @@ namespace BGC
|
|||
product.r2c2 = left.r2c1 * right.r1c2 + left.r2c2 * right.r2c2 + left.r2c3 * right.r3c2;
|
||||
}
|
||||
|
||||
public static void Get3x3At2x3(in Matrix3x3FP64 left, in Matrix2x3FP64 right, out Matrix2x3FP64 product)
|
||||
public static void Get3x3At2x3(in FP64Matrix3x3 left, in FP64Matrix2x3 right, out FP64Matrix2x3 product)
|
||||
{
|
||||
double r1c1 = left.r1c1 * right.r1c1 + left.r1c2 * right.r2c1 + left.r1c3 * right.r3c1;
|
||||
double r1c2 = left.r1c1 * right.r1c2 + left.r1c2 * right.r2c2 + left.r1c3 * right.r3c2;
|
||||
|
|
@ -127,7 +143,7 @@ namespace BGC
|
|||
product.r3c2 = r3c2;
|
||||
}
|
||||
|
||||
public static void Get3x3At3x3(in Matrix3x3FP64 left, in Matrix3x3FP64 right, out Matrix3x3FP64 product)
|
||||
public static void Get3x3At3x3(in FP64Matrix3x3 left, in FP64Matrix3x3 right, out FP64Matrix3x3 product)
|
||||
{
|
||||
double r1c1 = left.r1c1 * right.r1c1 + left.r1c2 * right.r2c1 + left.r1c3 * right.r3c1;
|
||||
double r1c2 = left.r1c1 * right.r1c2 + left.r1c2 * right.r2c2 + left.r1c3 * right.r3c2;
|
||||
204
BasicGeometry/FP64Quaternion.cs
Normal file
204
BasicGeometry/FP64Quaternion.cs
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public struct FP64Quaternion
|
||||
{
|
||||
public double s0 = 0.0, x1 = 0.0, x2 = 0.0, x3 = 0.0;
|
||||
|
||||
public FP64Quaternion(double s0, double x1, double x2, double x3)
|
||||
{
|
||||
this.s0 = s0;
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
}
|
||||
|
||||
public FP64Quaternion(in FP32Quaternion quaternion)
|
||||
{
|
||||
this.s0 = quaternion.s0;
|
||||
this.x1 = quaternion.x1;
|
||||
this.x2 = quaternion.x2;
|
||||
this.x3 = quaternion.x3;
|
||||
}
|
||||
|
||||
public FP64Quaternion(in FP64Quaternion quaternion)
|
||||
{
|
||||
this.s0 = quaternion.s0;
|
||||
this.x1 = quaternion.x1;
|
||||
this.x2 = quaternion.x2;
|
||||
this.x3 = quaternion.x3;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.s0 = 0.0;
|
||||
this.x1 = 0.0;
|
||||
this.x2 = 0.0;
|
||||
this.x3 = 0.0;
|
||||
}
|
||||
|
||||
public void Conjugate()
|
||||
{
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
this.x3 = -this.x3;
|
||||
}
|
||||
|
||||
public void SetValues(double s0, double x1, double x2, double x3)
|
||||
{
|
||||
this.s0 = s0;
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
}
|
||||
|
||||
public void SetValues(in FP32Quaternion quaternion)
|
||||
{
|
||||
this.s0 = quaternion.s0;
|
||||
this.x1 = quaternion.x1;
|
||||
this.x2 = quaternion.x2;
|
||||
this.x3 = quaternion.x3;
|
||||
}
|
||||
|
||||
public void SetValues(in FP64Quaternion quaternion)
|
||||
{
|
||||
this.s0 = quaternion.s0;
|
||||
this.x1 = quaternion.x1;
|
||||
this.x2 = quaternion.x2;
|
||||
this.x3 = quaternion.x3;
|
||||
}
|
||||
|
||||
public void SetConjugateOf(in FP64Quaternion quaternion)
|
||||
{
|
||||
this.s0 = quaternion.s0;
|
||||
this.x1 = -quaternion.x1;
|
||||
this.x2 = -quaternion.x2;
|
||||
this.x3 = -quaternion.x3;
|
||||
}
|
||||
|
||||
public readonly void MakeRotationMatrix(out FP64Matrix3x3 matrix)
|
||||
{
|
||||
double s0s0 = this.s0 * this.s0;
|
||||
double x1x1 = this.x1 * this.x1;
|
||||
double x2x2 = this.x2 * this.x2;
|
||||
double x3x3 = this.x3 * this.x3;
|
||||
|
||||
double squareModule = (s0s0 + x1x1) + (x2x2 + x3x3);
|
||||
|
||||
if (-FP64Utility.EPSYLON <= squareModule && squareModule <= FP64Utility.EPSYLON)
|
||||
{
|
||||
FP64Matrix3x3.LoadIdentity(out matrix);
|
||||
return;
|
||||
}
|
||||
|
||||
double corrector1;
|
||||
double corrector2;
|
||||
|
||||
if (1.0 - FP64Utility.TWO_EPSYLON <= squareModule && squareModule <= 1.0 + FP64Utility.TWO_EPSYLON) {
|
||||
corrector1 = 2.0 - squareModule;
|
||||
corrector2 = 2.0 * corrector1;
|
||||
}
|
||||
else {
|
||||
corrector1 = 1.0 / squareModule;
|
||||
corrector2 = 2.0 / squareModule;
|
||||
}
|
||||
|
||||
double s0x1 = this.s0 * this.x1;
|
||||
double s0x2 = this.s0 * this.x2;
|
||||
double s0x3 = this.s0 * this.x3;
|
||||
double x1x2 = this.x1 * this.x2;
|
||||
double x1x3 = this.x1 * this.x3;
|
||||
double x2x3 = this.x2 * this.x3;
|
||||
|
||||
matrix.r1c1 = corrector1 * ((s0s0 + x1x1) - (x2x2 + x3x3));
|
||||
matrix.r2c2 = corrector1 * ((s0s0 + x2x2) - (x1x1 + x3x3));
|
||||
matrix.r3c3 = corrector1 * ((s0s0 + x3x3) - (x1x1 + x2x2));
|
||||
|
||||
matrix.r1c2 = corrector2 * (x1x2 - s0x3);
|
||||
matrix.r2c3 = corrector2 * (x2x3 - s0x1);
|
||||
matrix.r3c1 = corrector2 * (x1x3 - s0x2);
|
||||
|
||||
matrix.r2c1 = corrector2 * (x1x2 + s0x3);
|
||||
matrix.r3c2 = corrector2 * (x2x3 + s0x1);
|
||||
matrix.r1c3 = corrector2 * (x1x3 + s0x2);
|
||||
}
|
||||
|
||||
public readonly void MakeReverseMatrix(out FP64Matrix3x3 matrix)
|
||||
{
|
||||
double s0s0 = this.s0 * this.s0;
|
||||
double x1x1 = this.x1 * this.x1;
|
||||
double x2x2 = this.x2 * this.x2;
|
||||
double x3x3 = this.x3 * this.x3;
|
||||
|
||||
double squareModule = (s0s0 + x1x1) + (x2x2 + x3x3);
|
||||
|
||||
if (-FP64Utility.EPSYLON <= squareModule && squareModule <= FP64Utility.EPSYLON)
|
||||
{
|
||||
FP64Matrix3x3.LoadIdentity(out matrix);
|
||||
return;
|
||||
}
|
||||
|
||||
double corrector1;
|
||||
double corrector2;
|
||||
|
||||
if (1.0 - FP64Utility.TWO_EPSYLON <= squareModule && squareModule <= 1.0 + FP64Utility.TWO_EPSYLON) {
|
||||
corrector1 = 2.0 - squareModule;
|
||||
corrector2 = 2.0 * corrector1;
|
||||
}
|
||||
else {
|
||||
corrector1 = 1.0 / squareModule;
|
||||
corrector2 = 2.0 / squareModule;
|
||||
}
|
||||
|
||||
double s0x1 = this.s0 * this.x1;
|
||||
double s0x2 = this.s0 * this.x2;
|
||||
double s0x3 = this.s0 * this.x3;
|
||||
double x1x2 = this.x1 * this.x2;
|
||||
double x1x3 = this.x1 * this.x3;
|
||||
double x2x3 = this.x2 * this.x3;
|
||||
|
||||
matrix.r1c1 = corrector1 * ((s0s0 + x1x1) - (x2x2 + x3x3));
|
||||
matrix.r2c2 = corrector1 * ((s0s0 + x2x2) - (x1x1 + x3x3));
|
||||
matrix.r3c3 = corrector1 * ((s0s0 + x3x3) - (x1x1 + x2x2));
|
||||
|
||||
matrix.r1c2 = corrector2 * (x1x2 + s0x3);
|
||||
matrix.r2c3 = corrector2 * (x2x3 + s0x1);
|
||||
matrix.r3c1 = corrector2 * (x1x3 + s0x2);
|
||||
|
||||
matrix.r2c1 = corrector2 * (x1x2 - s0x3);
|
||||
matrix.r3c2 = corrector2 * (x2x3 - s0x1);
|
||||
matrix.r1c3 = corrector2 * (x1x3 - s0x2);
|
||||
}
|
||||
|
||||
public static void Add(in FP64Quaternion quaternion1, in FP64Quaternion quaternion2, out FP64Quaternion sum)
|
||||
{
|
||||
sum.s0 = quaternion1.s0 + quaternion2.s0;
|
||||
sum.x1 = quaternion1.x1 + quaternion2.x1;
|
||||
sum.x2 = quaternion1.x2 + quaternion2.x2;
|
||||
sum.x3 = quaternion1.x3 + quaternion2.x3;
|
||||
}
|
||||
|
||||
public static void Subtract(in FP64Quaternion minuend, in FP64Quaternion subtrahend, out FP64Quaternion difference)
|
||||
{
|
||||
difference.s0 = minuend.s0 - subtrahend.s0;
|
||||
difference.x1 = minuend.x1 - subtrahend.x1;
|
||||
difference.x2 = minuend.x2 - subtrahend.x2;
|
||||
difference.x3 = minuend.x3 - subtrahend.x3;
|
||||
}
|
||||
|
||||
public static void Multiply(in FP64Quaternion left, in FP64Quaternion right, out FP64Quaternion product)
|
||||
{
|
||||
double s0 = (left.s0 * right.s0 - left.x1 * right.x1) - (left.x2 * right.x2 + left.x3 * right.x3);
|
||||
double x1 = (left.x1 * right.s0 + left.s0 * right.x1) - (left.x3 * right.x2 - left.x2 * right.x3);
|
||||
double x2 = (left.x2 * right.s0 + left.s0 * right.x2) - (left.x1 * right.x3 - left.x3 * right.x1);
|
||||
double x3 = (left.x3 * right.s0 + left.s0 * right.x3) - (left.x2 * right.x1 - left.x1 * right.x2);
|
||||
|
||||
product.s0 = s0;
|
||||
product.x1 = x1;
|
||||
product.x2 = x2;
|
||||
product.x3 = x3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 18 Nov 2024
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public class RadianFP64
|
||||
public class FP64Radians
|
||||
{
|
||||
public const double PI = 3.14159265358979324;
|
||||
public const double TWO_PI = 6.28318530717958648;
|
||||
|
|
@ -1,19 +1,19 @@
|
|||
/*
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 18 Nov 2024
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public class TurnFP64
|
||||
public class FP64Turns
|
||||
{
|
||||
public static double ToRadians(double turns)
|
||||
public static double TurnsToRadians(double turns)
|
||||
{
|
||||
return turns * RadianFP64.TWO_PI;
|
||||
return turns * FP64Radians.TWO_PI;
|
||||
}
|
||||
|
||||
public static double ToDegrees(double turns)
|
||||
public static double TurnsToDegrees(double turns)
|
||||
{
|
||||
return turns * 360.0;
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ namespace BGC
|
|||
{
|
||||
if (toUnit == AngleUnit.RADIANS)
|
||||
{
|
||||
return turns * RadianFP64.TWO_PI;
|
||||
return turns * FP64Radians.TWO_PI;
|
||||
}
|
||||
|
||||
if (toUnit == AngleUnit.DEGREES)
|
||||
20
BasicGeometry/FP64Utility.cs
Normal file
20
BasicGeometry/FP64Utility.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public class FP64Utility
|
||||
{
|
||||
public const double EPSYLON = 5E-14;
|
||||
public const double TWO_EPSYLON = 1E-13;
|
||||
public const double SQUARE_EPSYLON = 2.5E-27;
|
||||
|
||||
public const double EPSYLON_EFFECTIVENESS_LIMIT = 1.0;
|
||||
|
||||
public const double ONE_THIRD = 0.333333333333333333;
|
||||
public const double ONE_SIXTH = 0.166666666666666667;
|
||||
public const double ONE_NINETH = 0.111111111111111111;
|
||||
|
||||
public const double GOLDEN_RATIO_HIGH = 1.61803398874989485;
|
||||
public const double GOLDEN_RATIO_LOW = 0.61803398874989485;
|
||||
}
|
||||
}
|
||||
257
BasicGeometry/FP64Vector2.cs
Normal file
257
BasicGeometry/FP64Vector2.cs
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* Date: 1 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public struct FP64Vector2
|
||||
{
|
||||
public static readonly FP64Vector2 ZERO = new FP64Vector2(0.0, 0.0);
|
||||
|
||||
public double x1 = 0.0;
|
||||
public double x2 = 0.0;
|
||||
|
||||
public FP64Vector2(double x1, double x2)
|
||||
{
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
}
|
||||
|
||||
public FP64Vector2(in FP64Vector2 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
}
|
||||
|
||||
public FP64Vector2(in FP32Vector2 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
}
|
||||
|
||||
public readonly double GetSquareModule()
|
||||
{
|
||||
return this.x1 * this.x1 + this.x2 * this.x2;
|
||||
}
|
||||
|
||||
public readonly double GetModule()
|
||||
{
|
||||
return Math.Sqrt(this.GetSquareModule());
|
||||
}
|
||||
|
||||
public int Normalize()
|
||||
{
|
||||
double squareModule = this.GetSquareModule();
|
||||
|
||||
if (1.0 - FP64Utility.TWO_EPSYLON <= squareModule && squareModule <= 1.0 + FP64Utility.TWO_EPSYLON)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (squareModule <= FP64Utility.SQUARE_EPSYLON)
|
||||
{
|
||||
this.Reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
double module = Math.Sqrt(squareModule);
|
||||
|
||||
this.x1 /= module;
|
||||
this.x2 /= module;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public void Reverse()
|
||||
{
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
}
|
||||
|
||||
public readonly bool IsZero()
|
||||
{
|
||||
return this.GetSquareModule() <= FP64Utility.SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
public readonly bool IsUnit()
|
||||
{
|
||||
double squareModule = this.GetSquareModule();
|
||||
return 1.0 - FP64Utility.TWO_EPSYLON <= squareModule && squareModule <= FP64Utility.EPSYLON;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.x1 = 0.0;
|
||||
this.x2 = 0.0;
|
||||
}
|
||||
|
||||
public void SetValues(double x1, double x2)
|
||||
{
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
}
|
||||
|
||||
public void SetValues(in FP64Vector2 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
}
|
||||
|
||||
public void SetValues(in FP32Vector2 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
}
|
||||
|
||||
public void SetReverseOf(in FP64Vector2 vector)
|
||||
{
|
||||
this.x1 = -vector.x1;
|
||||
this.x2 = -vector.x2;
|
||||
}
|
||||
|
||||
public void SetReverseOf(in FP32Vector2 vector)
|
||||
{
|
||||
this.x1 = -vector.x1;
|
||||
this.x2 = -vector.x2;
|
||||
}
|
||||
|
||||
public void AppendScaled(FP64Vector2 summand, double scale)
|
||||
{
|
||||
this.x1 += summand.x1 * scale;
|
||||
this.x2 += summand.x2 * scale;
|
||||
}
|
||||
|
||||
public readonly override string ToString()
|
||||
{
|
||||
return String.Format("DPVector2({0}, {1})", this.x1, this.x2);
|
||||
}
|
||||
|
||||
public static void Add(in FP64Vector2 vector1, in FP64Vector2 vector2, out FP64Vector2 sum)
|
||||
{
|
||||
sum.x1 = vector1.x1 + vector2.x1;
|
||||
sum.x2 = vector1.x2 + vector2.x2;
|
||||
}
|
||||
|
||||
public static void Subtract(in FP64Vector2 minuend, in FP64Vector2 subtrahend, out FP64Vector2 difference)
|
||||
{
|
||||
difference.x1 = minuend.x1 - subtrahend.x1;
|
||||
difference.x2 = minuend.x2 - subtrahend.x2;
|
||||
}
|
||||
|
||||
public static void Multiply(in FP64Vector2 multiplicand, double multiplier, out FP64Vector2 product)
|
||||
{
|
||||
product.x1 = multiplicand.x1 * multiplier;
|
||||
product.x2 = multiplicand.x2 * multiplier;
|
||||
}
|
||||
|
||||
public static void Divide(in FP64Vector2 dividend, double divisor, out FP64Vector2 quotient)
|
||||
{
|
||||
Multiply(dividend, 1.0 / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void GetMean2(in FP64Vector2 vector1, in FP64Vector2 vector2, out FP64Vector2 result)
|
||||
{
|
||||
result.x1 = (vector1.x1 + vector2.x1) * 0.5;
|
||||
result.x2 = (vector1.x2 + vector2.x2) * 0.5;
|
||||
}
|
||||
|
||||
public static void GetMean3(in FP64Vector2 vector1, in FP64Vector2 vector2, in FP64Vector2 vector3, out FP64Vector2 result)
|
||||
{
|
||||
result.x1 = (vector1.x1 + vector2.x1 + vector3.x1) * FP64Utility.ONE_THIRD;
|
||||
result.x2 = (vector1.x2 + vector2.x2 + vector3.x2) * FP64Utility.ONE_THIRD;
|
||||
}
|
||||
|
||||
public static double GetScalarProduct(in FP64Vector2 vector1, in FP64Vector2 vector2)
|
||||
{
|
||||
return vector1.x1 * vector2.x1 + vector1.x2 * vector2.x2;
|
||||
}
|
||||
|
||||
public static double GetCrossProduct(in FP64Vector2 vector1, in FP64Vector2 vector2)
|
||||
{
|
||||
return vector1.x1 * vector2.x2 - vector1.x2 * vector2.x1;
|
||||
}
|
||||
|
||||
public static double GetAngle(in FP64Vector2 vector1, in FP64Vector2 vector2, AngleUnit unit)
|
||||
{
|
||||
double squareModule1 = vector1.GetSquareModule();
|
||||
|
||||
if (squareModule1 <= FP64Utility.SQUARE_EPSYLON)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double squareModule2 = vector2.GetSquareModule();
|
||||
|
||||
if (squareModule2 <= FP64Utility.SQUARE_EPSYLON)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double cosine = FP64Vector2.GetScalarProduct(vector1, vector2) / Math.Sqrt(squareModule1 * squareModule2);
|
||||
|
||||
if (1.0 - FP64Utility.EPSYLON <= cosine)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (cosine <= -(1.0 - FP64Utility.EPSYLON))
|
||||
{
|
||||
return FP64Angle.GetHalfCircle(unit);
|
||||
}
|
||||
|
||||
return FP64Radians.ToUnits(Math.Acos(cosine), unit);
|
||||
}
|
||||
|
||||
public static double GetSquareDistance(in FP64Vector2 vector1, in FP64Vector2 vector2)
|
||||
{
|
||||
double dx1 = vector1.x1 - vector2.x1;
|
||||
double dx2 = vector1.x2 - vector2.x2;
|
||||
|
||||
return dx1 * dx1 + dx2 * dx2;
|
||||
}
|
||||
|
||||
public static double GetDistance(in FP64Vector2 vector1, in FP64Vector2 vector2)
|
||||
{
|
||||
return Math.Sqrt(GetSquareDistance(vector1, vector2));
|
||||
}
|
||||
|
||||
public static bool AreEqual(in FP64Vector2 vector1, in FP64Vector2 vector2)
|
||||
{
|
||||
double squareModule1 = vector1.GetSquareModule();
|
||||
double squareModule2 = vector2.GetSquareModule();
|
||||
double squareModule3 = GetSquareDistance(vector1, vector2);
|
||||
|
||||
// 2.0 means dimension amount
|
||||
if (squareModule1 < FP64Utility.EPSYLON_EFFECTIVENESS_LIMIT || squareModule2 < FP64Utility.EPSYLON_EFFECTIVENESS_LIMIT)
|
||||
{
|
||||
return squareModule3 < (2.0 * FP64Utility.SQUARE_EPSYLON);
|
||||
}
|
||||
|
||||
if (squareModule1 <= squareModule2)
|
||||
{
|
||||
return squareModule3 <= (2.0 * FP64Utility.SQUARE_EPSYLON) * squareModule2;
|
||||
}
|
||||
|
||||
return squareModule3 <= (2.0 * FP64Utility.SQUARE_EPSYLON) * squareModule1;
|
||||
}
|
||||
}
|
||||
}
|
||||
300
BasicGeometry/FP64Vector3.cs
Normal file
300
BasicGeometry/FP64Vector3.cs
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* Date: 1 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public struct FP64Vector3
|
||||
{
|
||||
public static readonly FP64Vector3 ZERO = new FP64Vector3(0.0, 0.0, 0.0);
|
||||
|
||||
public double x1 = 0.0;
|
||||
public double x2 = 0.0;
|
||||
public double x3 = 0.0;
|
||||
|
||||
public FP64Vector3(double x1, double x2, double x3)
|
||||
{
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
}
|
||||
|
||||
public FP64Vector3(in FP64Vector3 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
this.x3 = vector.x3;
|
||||
}
|
||||
|
||||
public FP64Vector3(in FP32Vector3 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
this.x3 = vector.x3;
|
||||
}
|
||||
|
||||
public readonly double GetSquareModule()
|
||||
{
|
||||
return this.x1 * this.x1 + this.x2 * this.x2 + this.x3 * this.x3;
|
||||
}
|
||||
|
||||
public readonly double GetModule()
|
||||
{
|
||||
return Math.Sqrt(this.GetSquareModule());
|
||||
}
|
||||
|
||||
public int Normalize()
|
||||
{
|
||||
double squareModule = this.GetSquareModule();
|
||||
|
||||
if (1.0 - FP64Utility.TWO_EPSYLON <= squareModule && squareModule <= 1.0 + FP64Utility.TWO_EPSYLON)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (squareModule <= FP64Utility.SQUARE_EPSYLON)
|
||||
{
|
||||
this.Reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
double module = Math.Sqrt(squareModule);
|
||||
|
||||
this.x1 /= module;
|
||||
this.x2 /= module;
|
||||
this.x3 /= module;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public void Reverse()
|
||||
{
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
this.x3 = -this.x3;
|
||||
}
|
||||
|
||||
public readonly bool IsZero()
|
||||
{
|
||||
return this.GetSquareModule() <= FP64Utility.SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
public readonly bool IsUnit()
|
||||
{
|
||||
double squareModule = this.GetSquareModule();
|
||||
return 1.0 - FP64Utility.TWO_EPSYLON <= squareModule && squareModule <= FP64Utility.EPSYLON;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.x1 = 0.0;
|
||||
this.x2 = 0.0;
|
||||
this.x3 = 0.0;
|
||||
}
|
||||
|
||||
public void SetValues(double x1, double x2, double x3)
|
||||
{
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
}
|
||||
|
||||
public void SetValues(in FP64Vector3 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
this.x3 = vector.x3;
|
||||
}
|
||||
|
||||
public void SetValues(in FP32Vector3 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
this.x3 = vector.x3;
|
||||
}
|
||||
|
||||
public void SetReverseOf(in FP64Vector3 vector)
|
||||
{
|
||||
this.x1 = -vector.x1;
|
||||
this.x2 = -vector.x2;
|
||||
this.x3 = -vector.x3;
|
||||
}
|
||||
|
||||
public void SetReverseOf(in FP32Vector3 vector)
|
||||
{
|
||||
this.x1 = -vector.x1;
|
||||
this.x2 = -vector.x2;
|
||||
this.x3 = -vector.x3;
|
||||
}
|
||||
|
||||
public void AppendScaled(FP64Vector3 summand, double scale)
|
||||
{
|
||||
this.x1 += summand.x1 * scale;
|
||||
this.x2 += summand.x2 * scale;
|
||||
this.x3 += summand.x3 * scale;
|
||||
}
|
||||
|
||||
public readonly override string ToString()
|
||||
{
|
||||
return String.Format("DPVector3({0}, {1}, {2})", this.x1, this.x2, this.x3);
|
||||
}
|
||||
|
||||
public static void Add(in FP64Vector3 vector1, in FP64Vector3 vector2, out FP64Vector3 sum)
|
||||
{
|
||||
sum.x1 = vector1.x1 + vector2.x1;
|
||||
sum.x2 = vector1.x2 + vector2.x2;
|
||||
sum.x3 = vector1.x3 + vector2.x3;
|
||||
}
|
||||
|
||||
public static void Subtract(in FP64Vector3 minuend, in FP64Vector3 subtrahend, out FP64Vector3 difference)
|
||||
{
|
||||
difference.x1 = minuend.x1 - subtrahend.x1;
|
||||
difference.x2 = minuend.x2 - subtrahend.x2;
|
||||
difference.x3 = minuend.x3 - subtrahend.x3;
|
||||
}
|
||||
|
||||
public static void Multiply(in FP64Vector3 multiplicand, double multiplier, out FP64Vector3 product)
|
||||
{
|
||||
product.x1 = multiplicand.x1 * multiplier;
|
||||
product.x2 = multiplicand.x2 * multiplier;
|
||||
product.x3 = multiplicand.x3 * multiplier;
|
||||
}
|
||||
|
||||
public static void Divide(in FP64Vector3 dividend, double divisor, out FP64Vector3 quotient)
|
||||
{
|
||||
Multiply(dividend, 1.0 / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void GetMean2(in FP64Vector3 vector1, in FP64Vector3 vector2, out FP64Vector3 result)
|
||||
{
|
||||
result.x1 = (vector1.x1 + vector2.x1) * 0.5;
|
||||
result.x2 = (vector1.x2 + vector2.x2) * 0.5;
|
||||
result.x3 = (vector1.x3 + vector2.x3) * 0.5;
|
||||
}
|
||||
|
||||
public static void GetMean3(in FP64Vector3 vector1, in FP64Vector3 vector2, in FP64Vector3 vector3, out FP64Vector3 result)
|
||||
{
|
||||
result.x1 = (vector1.x1 + vector2.x1 + vector3.x1) * FP64Utility.ONE_THIRD;
|
||||
result.x2 = (vector1.x2 + vector2.x2 + vector3.x2) * FP64Utility.ONE_THIRD;
|
||||
result.x3 = (vector1.x3 + vector2.x3 + vector3.x3) * FP64Utility.ONE_THIRD;
|
||||
}
|
||||
|
||||
public static double GetScalarProduct(in FP64Vector3 vector1, in FP64Vector3 vector2)
|
||||
{
|
||||
return vector1.x1 * vector2.x1 + vector1.x2 * vector2.x2 + vector1.x3 * vector2.x3;
|
||||
}
|
||||
|
||||
public static void GetCrossProduct(in FP64Vector3 vector1, in FP64Vector3 vector2, out FP64Vector3 result)
|
||||
{
|
||||
double x1 = vector1.x2 * vector2.x3 - vector1.x3 * vector2.x2;
|
||||
double x2 = vector1.x3 * vector2.x1 - vector1.x1 * vector2.x3;
|
||||
double x3 = vector1.x1 * vector2.x2 - vector1.x2 * vector2.x1;
|
||||
|
||||
result.x1 = x1;
|
||||
result.x2 = x2;
|
||||
result.x3 = x3;
|
||||
}
|
||||
|
||||
public static double GetTripleProduct(in FP64Vector3 vector1, in FP64Vector3 vector2, in FP64Vector3 vector3)
|
||||
{
|
||||
return vector1.x1 * (vector2.x2 * vector3.x3 - vector2.x3 * vector3.x2)
|
||||
+ vector1.x2 * (vector2.x3 * vector3.x1 - vector2.x1 * vector3.x3)
|
||||
+ vector1.x3 * (vector2.x1 * vector3.x2 - vector2.x2 * vector3.x1);
|
||||
}
|
||||
|
||||
public static void GetDoubleCrossProduct(in FP64Vector3 vector1, in FP64Vector3 vector2, in FP64Vector3 vector3, out FP64Vector3 result)
|
||||
{
|
||||
// [a x [b x c]] = b * (a, c) - c * (a, b)
|
||||
double ac = GetScalarProduct(vector1, vector3);
|
||||
double ab = GetScalarProduct(vector1, vector2);
|
||||
|
||||
result.x1 = ac * vector2.x1 - ab * vector3.x1;
|
||||
result.x2 = ac * vector2.x2 - ab * vector3.x2;
|
||||
result.x3 = ac * vector2.x3 - ab * vector3.x3;
|
||||
}
|
||||
|
||||
public static double GetAngle(in FP64Vector3 vector1, in FP64Vector3 vector2, AngleUnit unit)
|
||||
{
|
||||
double squareModule1 = vector1.GetSquareModule();
|
||||
|
||||
if (squareModule1 <= FP64Utility.SQUARE_EPSYLON)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double squareModule2 = vector2.GetSquareModule();
|
||||
|
||||
if (squareModule2 <= FP64Utility.SQUARE_EPSYLON)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double cosine = FP64Vector3.GetScalarProduct(vector1, vector2) / Math.Sqrt(squareModule1 * squareModule2);
|
||||
|
||||
if (1.0 - FP64Utility.EPSYLON <= cosine)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (cosine <= -(1.0 - FP64Utility.EPSYLON))
|
||||
{
|
||||
return FP64Angle.GetHalfCircle(unit);
|
||||
}
|
||||
|
||||
return FP64Radians.ToUnits(Math.Acos(cosine), unit);
|
||||
}
|
||||
|
||||
public static double GetSquareDistance(in FP64Vector3 vector1, in FP64Vector3 vector2)
|
||||
{
|
||||
double dx1 = vector1.x1 - vector2.x1;
|
||||
double dx2 = vector1.x2 - vector2.x2;
|
||||
double dx3 = vector1.x3 - vector2.x3;
|
||||
|
||||
return dx1 * dx1 + dx2 * dx2 + dx3 * dx3;
|
||||
}
|
||||
|
||||
public static double GetDistance(in FP64Vector3 vector1, in FP64Vector3 vector2)
|
||||
{
|
||||
return Math.Sqrt(GetSquareDistance(vector1, vector2));
|
||||
}
|
||||
|
||||
public static bool AreEqual(in FP64Vector3 vector1, in FP64Vector3 vector2)
|
||||
{
|
||||
double squareModule1 = vector1.GetSquareModule();
|
||||
double squareModule2 = vector2.GetSquareModule();
|
||||
double squareModule3 = GetSquareDistance(vector1, vector2);
|
||||
|
||||
// 3.0 means dimension amount
|
||||
if (squareModule1 < FP64Utility.EPSYLON_EFFECTIVENESS_LIMIT || squareModule2 < FP64Utility.EPSYLON_EFFECTIVENESS_LIMIT)
|
||||
{
|
||||
return squareModule3 < (3.0 * FP64Utility.SQUARE_EPSYLON);
|
||||
}
|
||||
|
||||
if (squareModule1 <= squareModule2)
|
||||
{
|
||||
return squareModule3 <= (3.0 * FP64Utility.SQUARE_EPSYLON) * squareModule2;
|
||||
}
|
||||
|
||||
return squareModule3 <= (3.0 * FP64Utility.SQUARE_EPSYLON) * squareModule1;
|
||||
}
|
||||
}
|
||||
}
|
||||
312
BasicGeometry/FP64Versor.cs
Normal file
312
BasicGeometry/FP64Versor.cs
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
/*
|
||||
* Copyright 2019-2025 Andrey Pokidov <andrey.pokidov@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* Date: 20 Oct 2024
|
||||
*/
|
||||
|
||||
namespace BasicGeometry
|
||||
{
|
||||
public struct FP64Versor
|
||||
{
|
||||
private double s0 = 1.0;
|
||||
private double x1 = 0.0;
|
||||
private double x2 = 0.0;
|
||||
private double x3 = 0.0;
|
||||
|
||||
public FP64Versor(double s0, double x1, double x2, double x3)
|
||||
{
|
||||
LoadValues(s0, x1, x2, x3, out this);
|
||||
}
|
||||
|
||||
public FP64Versor(in FP64Versor versor)
|
||||
{
|
||||
this.s0 = versor.s0;
|
||||
this.x1 = versor.x1;
|
||||
this.x2 = versor.x2;
|
||||
this.x3 = versor.x3;
|
||||
}
|
||||
|
||||
public FP64Versor(in FP32Versor versor)
|
||||
{
|
||||
LoadValues(
|
||||
versor.GetScalar(),
|
||||
versor.GetX1(),
|
||||
versor.GetX2(),
|
||||
versor.GetX3(),
|
||||
out this);
|
||||
}
|
||||
|
||||
public readonly double GetScalar()
|
||||
{
|
||||
return this.s0;
|
||||
}
|
||||
|
||||
public readonly double GetX1()
|
||||
{
|
||||
return this.x1;
|
||||
}
|
||||
|
||||
public readonly double GetX2()
|
||||
{
|
||||
return this.x2;
|
||||
}
|
||||
|
||||
public readonly double GetX3()
|
||||
{
|
||||
return this.x3;
|
||||
}
|
||||
|
||||
public readonly bool IsIdle()
|
||||
{
|
||||
return this.s0 <= -(1.0 - FP64Utility.EPSYLON) || (1.0 - FP64Utility.EPSYLON) <= this.s0;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.s0 = 1.0;
|
||||
this.x1 = 0.0;
|
||||
this.x2 = 0.0;
|
||||
this.x3 = 0.0;
|
||||
}
|
||||
|
||||
public void Invert()
|
||||
{
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
this.x3 = -this.x3;
|
||||
}
|
||||
|
||||
public readonly double GetAngle(AngleUnit unit)
|
||||
{
|
||||
if (this.s0 <= -(1.0 - FP64Utility.TWO_EPSYLON) || 1.0 - FP64Utility.TWO_EPSYLON <= this.s0) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (-FP64Utility.EPSYLON <= this.s0 && this.s0 <= FP64Utility.EPSYLON)
|
||||
{
|
||||
return FP64Angle.GetHalfCircle(unit);
|
||||
}
|
||||
|
||||
return FP64Radians.ToUnits(2.0 * Math.Acos(s0), unit);
|
||||
}
|
||||
|
||||
public readonly void MakeRotationMatrix(out FP64Matrix3x3 matrix)
|
||||
{
|
||||
double s0s0 = this.s0 * this.s0;
|
||||
double x1x1 = this.x1 * this.x1;
|
||||
double x2x2 = this.x1 * this.x2;
|
||||
double x3x3 = this.x1 * this.x3;
|
||||
|
||||
|
||||
double s0x1 = 2.0 * this.s0 * this.x1;
|
||||
double s0x2 = 2.0 * this.s0 * this.x2;
|
||||
double s0x3 = 2.0 * this.s0 * this.x3;
|
||||
|
||||
double x1x2 = 2.0 * this.x1 * this.x2;
|
||||
double x1x3 = 2.0 * this.x1 * this.x3;
|
||||
double x2x3 = 2.0 * this.x2 * this.x3;
|
||||
|
||||
matrix.r1c1 = (s0s0 + x1x1) - (x2x2 + x3x3);
|
||||
matrix.r2c2 = (s0s0 + x2x2) - (x1x1 + x3x3);
|
||||
matrix.r3c3 = (s0s0 + x3x3) - (x1x1 + x2x2);
|
||||
|
||||
matrix.r1c2 = x1x2 - s0x3;
|
||||
matrix.r2c3 = x2x3 - s0x1;
|
||||
matrix.r3c1 = x1x3 - s0x2;
|
||||
|
||||
matrix.r2c1 = x1x2 + s0x3;
|
||||
matrix.r3c2 = x2x3 + s0x1;
|
||||
matrix.r1c3 = x1x3 + s0x2;
|
||||
}
|
||||
|
||||
public readonly void MakeReverseMatrix(out FP64Matrix3x3 matrix)
|
||||
{
|
||||
double s0s0 = this.s0 * this.s0;
|
||||
double x1x1 = this.x1 * this.x1;
|
||||
double x2x2 = this.x1 * this.x2;
|
||||
double x3x3 = this.x1 * this.x3;
|
||||
|
||||
double s0x1 = 2.0 * this.s0 * this.x1;
|
||||
double s0x2 = 2.0 * this.s0 * this.x2;
|
||||
double s0x3 = 2.0 * this.s0 * this.x3;
|
||||
|
||||
double x1x2 = 2.0 * this.x1 * this.x2;
|
||||
double x1x3 = 2.0 * this.x1 * this.x3;
|
||||
double x2x3 = 2.0 * this.x2 * this.x3;
|
||||
|
||||
matrix.r1c1 = (s0s0 + x1x1) - (x2x2 + x3x3);
|
||||
matrix.r2c2 = (s0s0 + x2x2) - (x1x1 + x3x3);
|
||||
matrix.r3c3 = (s0s0 + x3x3) - (x1x1 + x2x2);
|
||||
|
||||
matrix.r1c2 = x1x2 + s0x3;
|
||||
matrix.r2c3 = x2x3 + s0x1;
|
||||
matrix.r3c1 = x1x3 + s0x2;
|
||||
|
||||
matrix.r2c1 = x1x2 - s0x3;
|
||||
matrix.r3c2 = x2x3 - s0x1;
|
||||
matrix.r1c3 = x1x3 - s0x2;
|
||||
}
|
||||
|
||||
public void SetValues(double s0, double x1, double x2, double x3)
|
||||
{
|
||||
this.s0 = s0;
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
|
||||
double squareModule = (s0 * s0 + x1 * x1) + (x2 * x2 + x3 * x3);
|
||||
|
||||
if (1.0 - FP64Utility.TWO_EPSYLON <= squareModule && squareModule <= 1.0 + FP64Utility.TWO_EPSYLON)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.Normalize(squareModule);
|
||||
}
|
||||
|
||||
public void SetValues(in FP64Versor versor)
|
||||
{
|
||||
this.s0 = versor.s0;
|
||||
this.x1 = versor.x1;
|
||||
this.x2 = versor.x2;
|
||||
this.x3 = versor.x3;
|
||||
}
|
||||
|
||||
public void SetValues(in FP32Versor versor)
|
||||
{
|
||||
LoadValues(
|
||||
versor.GetScalar(),
|
||||
versor.GetX1(),
|
||||
versor.GetX2(),
|
||||
versor.GetX3(),
|
||||
out this);
|
||||
}
|
||||
|
||||
public void SetInverted(in FP64Versor versor)
|
||||
{
|
||||
this.s0 = versor.s0;
|
||||
this.x1 = -versor.x1;
|
||||
this.x2 = -versor.x2;
|
||||
this.x3 = -versor.x3;
|
||||
}
|
||||
|
||||
public void SetInverted(in FP32Versor versor)
|
||||
{
|
||||
LoadValues(
|
||||
versor.GetScalar(),
|
||||
versor.GetX1(),
|
||||
versor.GetX2(),
|
||||
versor.GetX3(),
|
||||
out this);
|
||||
}
|
||||
|
||||
public readonly void Turn(in FP64Vector3 vector, out FP64Vector3 result)
|
||||
{
|
||||
double tx1 = 2.0 * (this.x2 * vector.x3 - this.x3 * vector.x2);
|
||||
double tx2 = 2.0 * (this.x3 * vector.x1 - this.x1 * vector.x3);
|
||||
double tx3 = 2.0 * (this.x1 * vector.x2 - this.x2 * vector.x1);
|
||||
|
||||
double x1 = (vector.x1 + tx1 * this.s0) + (this.x2 * tx3 - this.x3 * tx2);
|
||||
double x2 = (vector.x2 + tx2 * this.s0) + (this.x3 * tx1 - this.x1 * tx3);
|
||||
double x3 = (vector.x3 + tx3 * this.s0) + (this.x1 * tx2 - this.x2 * tx1);
|
||||
|
||||
result.x1 = x1;
|
||||
result.x2 = x2;
|
||||
result.x3 = x3;
|
||||
}
|
||||
|
||||
public readonly void TurnBack(in FP64Vector3 vector, out FP64Vector3 result)
|
||||
{
|
||||
double tx1 = 2.0 * (this.x2 * vector.x3 - this.x3 * vector.x2);
|
||||
double tx2 = 2.0 * (this.x3 * vector.x1 - this.x1 * vector.x3);
|
||||
double tx3 = 2.0 * (this.x1 * vector.x2 - this.x2 * vector.x1);
|
||||
|
||||
double x1 = (vector.x1 - tx1 * this.s0) + (this.x2 * tx3 - this.x3 * tx2);
|
||||
double x2 = (vector.x2 - tx2 * this.s0) + (this.x3 * tx1 - this.x1 * tx3);
|
||||
double x3 = (vector.x3 - tx3 * this.s0) + (this.x1 * tx2 - this.x2 * tx1);
|
||||
|
||||
result.x1 = x1;
|
||||
result.x2 = x2;
|
||||
result.x3 = x3;
|
||||
}
|
||||
|
||||
private void Normalize(double squareModule)
|
||||
{
|
||||
if (squareModule <= FP64Utility.SQUARE_EPSYLON || (this.x1 * this.x1 + this.x2 * this.x2 + this.x3 * this.x3) <= FP64Utility.SQUARE_EPSYLON * squareModule)
|
||||
{
|
||||
this.Reset();
|
||||
return;
|
||||
}
|
||||
|
||||
double module = Math.Sqrt(squareModule);
|
||||
|
||||
this.s0 /= module;
|
||||
this.x1 /= module;
|
||||
this.x2 /= module;
|
||||
this.x3 /= module;
|
||||
}
|
||||
|
||||
public static void Combine(in FP64Versor second, in FP64Versor first, out FP64Versor result)
|
||||
{
|
||||
double s0 = (second.s0 * first.s0 - second.x1 * first.x1) - (second.x2 * first.x2 + second.x3 * first.x3);
|
||||
double x1 = (second.x1 * first.s0 + second.s0 * first.x1) - (second.x3 * first.x2 - second.x2 * first.x3);
|
||||
double x2 = (second.x2 * first.s0 + second.s0 * first.x2) - (second.x1 * first.x3 - second.x3 * first.x1);
|
||||
double x3 = (second.x3 * first.s0 + second.s0 * first.x3) - (second.x2 * first.x1 - second.x1 * first.x2);
|
||||
|
||||
double squareModule = (s0 * s0 + x1 * x1) + (x2 * x2 + x3 * x3);
|
||||
|
||||
result.s0 = s0;
|
||||
result.x1 = x1;
|
||||
result.x2 = x2;
|
||||
result.x3 = x3;
|
||||
|
||||
if (1.0 - FP64Utility.TWO_EPSYLON <= squareModule && squareModule <= 1.0 + FP64Utility.TWO_EPSYLON)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
result.Normalize(squareModule);
|
||||
}
|
||||
|
||||
public static void LoadIdle(out FP64Versor versor)
|
||||
{
|
||||
versor.s0 = 1.0;
|
||||
versor.x1 = 0.0;
|
||||
versor.x2 = 0.0;
|
||||
versor.x3 = 0.0;
|
||||
}
|
||||
|
||||
public static void LoadValues(double s0, double x1, double x2, double x3, out FP64Versor versor)
|
||||
{
|
||||
versor.s0 = s0;
|
||||
versor.x1 = x1;
|
||||
versor.x2 = x2;
|
||||
versor.x3 = x3;
|
||||
|
||||
double squareModule = (s0 * s0 + x1 * x1) + (x2 * x2 + x3 * x3);
|
||||
|
||||
if (1.0 - FP64Utility.TWO_EPSYLON <= squareModule && squareModule <= 1.0 + FP64Utility.TWO_EPSYLON)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
versor.Normalize(squareModule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,504 +0,0 @@
|
|||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 4 Dec 2024
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
{
|
||||
public struct QuaternionFP32
|
||||
{
|
||||
public float s0 = 0.0f, x1 = 0.0f, x2 = 0.0f, x3 = 0.0f;
|
||||
|
||||
public QuaternionFP32(float s0, float x1, float x2, float x3)
|
||||
{
|
||||
this.s0 = s0;
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
}
|
||||
|
||||
public QuaternionFP32(in QuaternionFP32 quaternion)
|
||||
{
|
||||
this.s0 = quaternion.s0;
|
||||
this.x1 = quaternion.x1;
|
||||
this.x2 = quaternion.x2;
|
||||
this.x3 = quaternion.x3;
|
||||
}
|
||||
|
||||
public QuaternionFP32(in QuaternionFP64 quaternion)
|
||||
{
|
||||
this.s0 = (float)quaternion.s0;
|
||||
this.x1 = (float)quaternion.x1;
|
||||
this.x2 = (float)quaternion.x2;
|
||||
this.x3 = (float)quaternion.x3;
|
||||
}
|
||||
|
||||
public readonly float GetSquareModulus()
|
||||
{
|
||||
return this.s0 * this.s0 + this.x1 * this.x1 + (this.x2 * this.x2 + this.x3 * this.x3);
|
||||
}
|
||||
|
||||
public readonly float GetModulus()
|
||||
{
|
||||
return MathF.Sqrt(this.GetSquareModulus());
|
||||
}
|
||||
|
||||
public readonly bool IsZero()
|
||||
{
|
||||
return this.GetSquareModulus() <= UtilityFP32.SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
public readonly bool IsUnit()
|
||||
{
|
||||
return UtilityFP32.IsSqareUnit(this.GetSquareModulus());
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.s0 = 0.0f;
|
||||
this.x1 = 0.0f;
|
||||
this.x2 = 0.0f;
|
||||
this.x3 = 0.0f;
|
||||
}
|
||||
|
||||
public void MakeUnit()
|
||||
{
|
||||
this.s0 = 1.0f;
|
||||
this.x1 = 0.0f;
|
||||
this.x2 = 0.0f;
|
||||
this.x3 = 0.0f;
|
||||
}
|
||||
|
||||
public void Conjugate()
|
||||
{
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
this.x3 = -this.x3;
|
||||
}
|
||||
|
||||
public void MakeOpposit()
|
||||
{
|
||||
this.s0 = -this.s0;
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
this.x3 = -this.x3;
|
||||
}
|
||||
|
||||
public bool Invert()
|
||||
{
|
||||
float squareModulus = this.GetSquareModulus();
|
||||
|
||||
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON || float.IsNaN(squareModulus))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float multiplicand = 1.0f / squareModulus;
|
||||
|
||||
this.s0 = this.s0 * multiplicand;
|
||||
this.x1 = -this.x1 * multiplicand;
|
||||
this.x2 = -this.x2 * multiplicand;
|
||||
this.x3 = -this.x3 * multiplicand;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Normalize()
|
||||
{
|
||||
float squareModulus = this.GetSquareModulus();
|
||||
|
||||
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON || float.IsNaN(squareModulus))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float multiplier = MathF.Sqrt(1.0f / squareModulus);
|
||||
|
||||
this.s0 *= multiplier;
|
||||
this.x1 *= multiplier;
|
||||
this.x2 *= multiplier;
|
||||
this.x3 *= multiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetValues(float s0, float x1, float x2, float x3)
|
||||
{
|
||||
this.s0 = s0;
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
}
|
||||
|
||||
public void SetValues(in QuaternionFP32 quaternion)
|
||||
{
|
||||
this.s0 = quaternion.s0;
|
||||
this.x1 = quaternion.x1;
|
||||
this.x2 = quaternion.x2;
|
||||
this.x3 = quaternion.x3;
|
||||
}
|
||||
|
||||
public void SetValues(in QuaternionFP64 quaternion)
|
||||
{
|
||||
this.s0 = (float)quaternion.s0;
|
||||
this.x1 = (float)quaternion.x1;
|
||||
this.x2 = (float)quaternion.x2;
|
||||
this.x3 = (float)quaternion.x3;
|
||||
}
|
||||
|
||||
public static void Reset(out QuaternionFP32 quaternion)
|
||||
{
|
||||
quaternion.s0 = 0.0f;
|
||||
quaternion.x1 = 0.0f;
|
||||
quaternion.x2 = 0.0f;
|
||||
quaternion.x3 = 0.0f;
|
||||
}
|
||||
|
||||
public static void MakeUnit(out QuaternionFP32 quaternion)
|
||||
{
|
||||
quaternion.s0 = 1.0f;
|
||||
quaternion.x1 = 0.0f;
|
||||
quaternion.x2 = 0.0f;
|
||||
quaternion.x3 = 0.0f;
|
||||
}
|
||||
|
||||
public static void Swap(ref QuaternionFP32 quaternion1, ref QuaternionFP32 quaternion2)
|
||||
{
|
||||
float s0 = quaternion1.s0;
|
||||
float x1 = quaternion1.x1;
|
||||
float x2 = quaternion1.x2;
|
||||
float x3 = quaternion1.x3;
|
||||
|
||||
quaternion1.s0 = quaternion2.s0;
|
||||
quaternion1.x1 = quaternion2.x1;
|
||||
quaternion1.x2 = quaternion2.x2;
|
||||
quaternion1.x3 = quaternion2.x3;
|
||||
|
||||
quaternion2.s0 = s0;
|
||||
quaternion2.x1 = x1;
|
||||
quaternion2.x2 = x2;
|
||||
quaternion2.x3 = x3;
|
||||
}
|
||||
|
||||
public static void Add(in QuaternionFP32 quaternion1, in QuaternionFP32 quaternion2, out QuaternionFP32 sum)
|
||||
{
|
||||
sum.s0 = quaternion1.s0 + quaternion2.s0;
|
||||
sum.x1 = quaternion1.x1 + quaternion2.x1;
|
||||
sum.x2 = quaternion1.x2 + quaternion2.x2;
|
||||
sum.x3 = quaternion1.x3 + quaternion2.x3;
|
||||
}
|
||||
|
||||
public static void AddScaled(in QuaternionFP32 basic_quaternion, in QuaternionFP32 scalable_quaternion, float scale, out QuaternionFP32 sum)
|
||||
{
|
||||
sum.s0 = basic_quaternion.s0 + scale * scalable_quaternion.s0;
|
||||
sum.x1 = basic_quaternion.x1 + scale * scalable_quaternion.x1;
|
||||
sum.x2 = basic_quaternion.x2 + scale * scalable_quaternion.x2;
|
||||
sum.x3 = basic_quaternion.x3 + scale * scalable_quaternion.x3;
|
||||
}
|
||||
|
||||
public static void Subtract(in QuaternionFP32 minuend, in QuaternionFP32 subtrahend, out QuaternionFP32 difference)
|
||||
{
|
||||
difference.s0 = minuend.s0 - subtrahend.s0;
|
||||
difference.x1 = minuend.x1 - subtrahend.x1;
|
||||
difference.x2 = minuend.x2 - subtrahend.x2;
|
||||
difference.x3 = minuend.x3 - subtrahend.x3;
|
||||
}
|
||||
|
||||
public static void Multiply(in QuaternionFP32 left, in QuaternionFP32 right, out QuaternionFP32 product)
|
||||
{
|
||||
float s0 = left.s0 * right.s0 - left.x1 * right.x1 - (left.x2 * right.x2 + left.x3 * right.x3);
|
||||
float x1 = left.x1 * right.s0 + left.s0 * right.x1 - (left.x3 * right.x2 - left.x2 * right.x3);
|
||||
float x2 = left.x2 * right.s0 + left.s0 * right.x2 - (left.x1 * right.x3 - left.x3 * right.x1);
|
||||
float x3 = left.x3 * right.s0 + left.s0 * right.x3 - (left.x2 * right.x1 - left.x1 * right.x2);
|
||||
|
||||
product.s0 = s0;
|
||||
product.x1 = x1;
|
||||
product.x2 = x2;
|
||||
product.x3 = x3;
|
||||
}
|
||||
|
||||
public static void Multiply(in QuaternionFP32 quaternion, float multiplier, out QuaternionFP32 product)
|
||||
{
|
||||
product.s0 = quaternion.s0 * multiplier;
|
||||
product.x1 = quaternion.x1 * multiplier;
|
||||
product.x2 = quaternion.x2 * multiplier;
|
||||
product.x3 = quaternion.x3 * multiplier;
|
||||
}
|
||||
|
||||
public static bool Divide(in QuaternionFP32 divident, in QuaternionFP32 divisor, out QuaternionFP32 quotient)
|
||||
{
|
||||
float squareModulus = divisor.GetSquareModulus();
|
||||
|
||||
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON || float.IsNaN(squareModulus))
|
||||
{
|
||||
Reset(out quotient);
|
||||
return false;
|
||||
}
|
||||
|
||||
float s0 = (divident.s0 * divisor.s0 + divident.x1 * divisor.x1) + (divident.x2 * divisor.x2 + divident.x3 * divisor.x3);
|
||||
float x1 = (divident.x1 * divisor.s0 + divident.x3 * divisor.x2) - (divident.s0 * divisor.x1 + divident.x2 * divisor.x3);
|
||||
float x2 = (divident.x2 * divisor.s0 + divident.x1 * divisor.x3) - (divident.s0 * divisor.x2 + divident.x3 * divisor.x1);
|
||||
float x3 = (divident.x3 * divisor.s0 + divident.x2 * divisor.x1) - (divident.s0 * divisor.x3 + divident.x1 * divisor.x2);
|
||||
|
||||
float multiplicand = 1.0f / squareModulus;
|
||||
|
||||
quotient.s0 = s0 * multiplicand;
|
||||
quotient.x1 = x1 * multiplicand;
|
||||
quotient.x2 = x2 * multiplicand;
|
||||
quotient.x3 = x3 * multiplicand;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Divide(in QuaternionFP32 divident, float divisor, out QuaternionFP32 quotient)
|
||||
{
|
||||
Multiply(divident, 1.0f / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void GetMeanOfTwo(in QuaternionFP32 vector1, in QuaternionFP32 vector2, out QuaternionFP32 mean)
|
||||
{
|
||||
mean.s0 = (vector1.s0 + vector2.s0) * 0.5f;
|
||||
mean.x1 = (vector1.x1 + vector2.x1) * 0.5f;
|
||||
mean.x2 = (vector1.x2 + vector2.x2) * 0.5f;
|
||||
mean.x3 = (vector1.x3 + vector2.x3) * 0.5f;
|
||||
}
|
||||
|
||||
public static void GetMeanOfThree(in QuaternionFP32 vector1, in QuaternionFP32 vector2, in QuaternionFP32 vector3, out QuaternionFP32 mean)
|
||||
{
|
||||
mean.s0 = (vector1.s0 + vector2.s0 + vector3.s0) * UtilityFP32.ONE_THIRD;
|
||||
mean.x1 = (vector1.x1 + vector2.x1 + vector3.x1) * UtilityFP32.ONE_THIRD;
|
||||
mean.x2 = (vector1.x2 + vector2.x2 + vector3.x2) * UtilityFP32.ONE_THIRD;
|
||||
mean.x3 = (vector1.x3 + vector2.x3 + vector3.x3) * UtilityFP32.ONE_THIRD;
|
||||
}
|
||||
|
||||
public static void Interpolate(in QuaternionFP32 quaternion1, in QuaternionFP32 quaternion2, float phase, out QuaternionFP32 interpolation)
|
||||
{
|
||||
float counterphase = 1.0f - phase;
|
||||
|
||||
interpolation.s0 = quaternion1.s0 * counterphase + quaternion2.s0 * phase;
|
||||
interpolation.x1 = quaternion1.x1 * counterphase + quaternion2.x1 * phase;
|
||||
interpolation.x2 = quaternion1.x2 * counterphase + quaternion2.x2 * phase;
|
||||
interpolation.x3 = quaternion1.x3 * counterphase + quaternion2.x3 * phase;
|
||||
}
|
||||
|
||||
public static void GetConjugate(in QuaternionFP32 quaternion, out QuaternionFP32 conjugate)
|
||||
{
|
||||
conjugate.s0 = quaternion.s0;
|
||||
conjugate.x1 = -quaternion.x1;
|
||||
conjugate.x2 = -quaternion.x2;
|
||||
conjugate.x3 = -quaternion.x3;
|
||||
}
|
||||
|
||||
public static void GetOpposite(in QuaternionFP32 quaternion, out QuaternionFP32 opposit)
|
||||
{
|
||||
opposit.s0 = -quaternion.s0;
|
||||
opposit.x1 = -quaternion.x1;
|
||||
opposit.x2 = -quaternion.x2;
|
||||
opposit.x3 = -quaternion.x3;
|
||||
}
|
||||
|
||||
public static bool GetInverse(in QuaternionFP32 quaternion, out QuaternionFP32 inverse)
|
||||
{
|
||||
float squareModulus = quaternion.GetSquareModulus();
|
||||
|
||||
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON || float.IsNaN(squareModulus))
|
||||
{
|
||||
Reset(out inverse);
|
||||
return false;
|
||||
}
|
||||
|
||||
float multiplicand = 1.0f / squareModulus;
|
||||
|
||||
inverse.s0 = quaternion.s0 * multiplicand;
|
||||
inverse.x1 = -quaternion.x1 * multiplicand;
|
||||
inverse.x2 = -quaternion.x2 * multiplicand;
|
||||
inverse.x3 = -quaternion.x3 * multiplicand;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool GetNormalized(in QuaternionFP32 quaternion, out QuaternionFP32 normalized)
|
||||
{
|
||||
float squareModulus = quaternion.GetSquareModulus();
|
||||
|
||||
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON || float.IsNaN(squareModulus))
|
||||
{
|
||||
Reset(out normalized);
|
||||
return false;
|
||||
}
|
||||
|
||||
float multiplier = MathF.Sqrt(1.0f / squareModulus);
|
||||
|
||||
normalized.s0 = quaternion.s0 * multiplier;
|
||||
normalized.x1 = quaternion.x1 * multiplier;
|
||||
normalized.x2 = quaternion.x2 * multiplier;
|
||||
normalized.x3 = quaternion.x3 * multiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool GetExponation(in QuaternionFP32 quaternion, float exponent, out QuaternionFP32 power)
|
||||
{
|
||||
float s0s0 = quaternion.s0 * quaternion.s0;
|
||||
float x1x1 = quaternion.x1 * quaternion.x1;
|
||||
float x2x2 = quaternion.x2 * quaternion.x2;
|
||||
float x3x3 = quaternion.x3 * quaternion.x3;
|
||||
|
||||
float squareVector = x1x1 + (x2x2 + x3x3);
|
||||
float squareModulus = (s0s0 + x1x1) + (x2x2 + x3x3);
|
||||
|
||||
if (float.IsNaN(squareModulus))
|
||||
{
|
||||
Reset(out power);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON)
|
||||
{
|
||||
Reset(out power);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (squareVector <= UtilityFP32.SQUARE_EPSYLON)
|
||||
{
|
||||
if (quaternion.s0 < 0.0f)
|
||||
{
|
||||
Reset(out power);
|
||||
return false;
|
||||
}
|
||||
|
||||
power.s0 = MathF.Pow(quaternion.s0, exponent);
|
||||
power.x1 = 0.0f;
|
||||
power.x2 = 0.0f;
|
||||
power.x3 = 0.0f;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float sine = MathF.Sqrt(squareVector / squareModulus);
|
||||
float power_angle = MathF.Atan2(sine, quaternion.s0 / MathF.Sqrt(squareModulus)) * exponent;
|
||||
float power_modulus = MathF.Pow(squareModulus, 0.5f * exponent);
|
||||
float multiplier = power_modulus * MathF.Sin(power_angle) / sine;
|
||||
|
||||
power.s0 = power_modulus * MathF.Cos(power_angle);
|
||||
power.x1 = quaternion.x1 * multiplier;
|
||||
power.x2 = quaternion.x2 * multiplier;
|
||||
power.x3 = quaternion.x3 * multiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool GetRotationMatrix(in QuaternionFP32 quaternion, out Matrix3x3FP32 matrix)
|
||||
{
|
||||
float s0s0 = quaternion.s0 * quaternion.s0;
|
||||
float x1x1 = quaternion.x1 * quaternion.x1;
|
||||
float x2x2 = quaternion.x2 * quaternion.x2;
|
||||
float x3x3 = quaternion.x3 * quaternion.x3;
|
||||
|
||||
float squareModulus = s0s0 + x1x1 + (x2x2 + x3x3);
|
||||
|
||||
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON)
|
||||
{
|
||||
Matrix3x3FP32.LoadIdentity(out matrix);
|
||||
return false;
|
||||
}
|
||||
|
||||
float corrector1 = 1.0f / squareModulus;
|
||||
|
||||
float s0x1 = quaternion.s0 * quaternion.x1;
|
||||
float s0x2 = quaternion.s0 * quaternion.x2;
|
||||
float s0x3 = quaternion.s0 * quaternion.x3;
|
||||
float x1x2 = quaternion.x1 * quaternion.x2;
|
||||
float x1x3 = quaternion.x1 * quaternion.x3;
|
||||
float x2x3 = quaternion.x2 * quaternion.x3;
|
||||
|
||||
float corrector2 = 2.0f * corrector1;
|
||||
|
||||
matrix.r1c1 = corrector1 * ((s0s0 + x1x1) - (x2x2 + x3x3));
|
||||
matrix.r2c2 = corrector1 * ((s0s0 + x2x2) - (x1x1 + x3x3));
|
||||
matrix.r3c3 = corrector1 * ((s0s0 + x3x3) - (x1x1 + x2x2));
|
||||
|
||||
matrix.r1c2 = corrector2 * (x1x2 - s0x3);
|
||||
matrix.r2c3 = corrector2 * (x2x3 - s0x1);
|
||||
matrix.r3c1 = corrector2 * (x1x3 - s0x2);
|
||||
|
||||
matrix.r2c1 = corrector2 * (x1x2 + s0x3);
|
||||
matrix.r3c2 = corrector2 * (x2x3 + s0x1);
|
||||
matrix.r1c3 = corrector2 * (x1x3 + s0x2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool GetReverseMatrix(in QuaternionFP32 quaternion, out Matrix3x3FP32 matrix)
|
||||
{
|
||||
float s0s0 = quaternion.s0 * quaternion.s0;
|
||||
float x1x1 = quaternion.x1 * quaternion.x1;
|
||||
float x2x2 = quaternion.x2 * quaternion.x2;
|
||||
float x3x3 = quaternion.x3 * quaternion.x3;
|
||||
|
||||
float squareModulus = s0s0 + x1x1 + (x2x2 + x3x3);
|
||||
|
||||
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON)
|
||||
{
|
||||
Matrix3x3FP32.LoadIdentity(out matrix);
|
||||
return false;
|
||||
}
|
||||
|
||||
float corrector1 = 1.0f / squareModulus;
|
||||
|
||||
float s0x1 = quaternion.s0 * quaternion.x1;
|
||||
float s0x2 = quaternion.s0 * quaternion.x2;
|
||||
float s0x3 = quaternion.s0 * quaternion.x3;
|
||||
float x1x2 = quaternion.x1 * quaternion.x2;
|
||||
float x1x3 = quaternion.x1 * quaternion.x3;
|
||||
float x2x3 = quaternion.x2 * quaternion.x3;
|
||||
|
||||
float corrector2 = 2.0f * corrector1;
|
||||
|
||||
matrix.r1c1 = corrector1 * ((s0s0 + x1x1) - (x2x2 + x3x3));
|
||||
matrix.r2c2 = corrector1 * ((s0s0 + x2x2) - (x1x1 + x3x3));
|
||||
matrix.r3c3 = corrector1 * ((s0s0 + x3x3) - (x1x1 + x2x2));
|
||||
|
||||
matrix.r1c2 = corrector2 * (x1x2 + s0x3);
|
||||
matrix.r2c3 = corrector2 * (x2x3 + s0x1);
|
||||
matrix.r3c1 = corrector2 * (x1x3 + s0x2);
|
||||
|
||||
matrix.r2c1 = corrector2 * (x1x2 - s0x3);
|
||||
matrix.r3c2 = corrector2 * (x2x3 - s0x1);
|
||||
matrix.r1c3 = corrector2 * (x1x3 - s0x2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool GetBothMatrices(in QuaternionFP32 quaternion, out Matrix3x3FP32 matrix, out Matrix3x3FP32 reverse)
|
||||
{
|
||||
if (GetReverseMatrix(quaternion, out reverse))
|
||||
{
|
||||
Matrix3x3FP32.MakeTransposed(reverse, out matrix);
|
||||
return true;
|
||||
}
|
||||
|
||||
Matrix3x3FP32.LoadIdentity(out matrix);
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool AreClose(in QuaternionFP32 quaternion1, in QuaternionFP32 quaternion2)
|
||||
{
|
||||
float ds0 = quaternion1.s0 - quaternion2.s0;
|
||||
float dx1 = quaternion1.x1 - quaternion2.x1;
|
||||
float dx2 = quaternion1.x2 - quaternion2.x2;
|
||||
float dx3 = quaternion1.x3 - quaternion2.x3;
|
||||
|
||||
float squareModulus1 = quaternion1.GetSquareModulus();
|
||||
float squareModulus2 = quaternion2.GetSquareModulus();
|
||||
float squareDistance = (ds0 * ds0 + dx1 * dx1) + (dx2 * dx2 + dx3 * dx3);
|
||||
|
||||
if (squareModulus1 <= UtilityFP32.EPSYLON_EFFECTIVENESS_LIMIT || squareModulus2 <= UtilityFP32.EPSYLON_EFFECTIVENESS_LIMIT) {
|
||||
return squareDistance <= UtilityFP32.SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
return squareDistance <= UtilityFP32.SQUARE_EPSYLON * squareModulus1 && squareDistance <= UtilityFP32.SQUARE_EPSYLON * squareModulus2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,504 +0,0 @@
|
|||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 4 Dec 2024
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
{
|
||||
public struct QuaternionFP64
|
||||
{
|
||||
public double s0 = 0.0, x1 = 0.0, x2 = 0.0, x3 = 0.0;
|
||||
|
||||
public QuaternionFP64(double s0, double x1, double x2, double x3)
|
||||
{
|
||||
this.s0 = s0;
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
}
|
||||
|
||||
public QuaternionFP64(in QuaternionFP64 quaternion)
|
||||
{
|
||||
this.s0 = quaternion.s0;
|
||||
this.x1 = quaternion.x1;
|
||||
this.x2 = quaternion.x2;
|
||||
this.x3 = quaternion.x3;
|
||||
}
|
||||
|
||||
public QuaternionFP64(in QuaternionFP32 quaternion)
|
||||
{
|
||||
this.s0 = quaternion.s0;
|
||||
this.x1 = quaternion.x1;
|
||||
this.x2 = quaternion.x2;
|
||||
this.x3 = quaternion.x3;
|
||||
}
|
||||
|
||||
public readonly double GetSquareModulus()
|
||||
{
|
||||
return this.s0 * this.s0 + this.x1 * this.x1 + (this.x2 * this.x2 + this.x3 * this.x3);
|
||||
}
|
||||
|
||||
public readonly double GetModulus()
|
||||
{
|
||||
return Math.Sqrt(this.GetSquareModulus());
|
||||
}
|
||||
|
||||
public readonly bool IsZero()
|
||||
{
|
||||
return this.GetSquareModulus() <= UtilityFP64.SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
public readonly bool IsUnit()
|
||||
{
|
||||
return UtilityFP64.IsSqareUnit(this.GetSquareModulus());
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.s0 = 0.0;
|
||||
this.x1 = 0.0;
|
||||
this.x2 = 0.0;
|
||||
this.x3 = 0.0;
|
||||
}
|
||||
|
||||
public void MakeUnit()
|
||||
{
|
||||
this.s0 = 1.0;
|
||||
this.x1 = 0.0;
|
||||
this.x2 = 0.0;
|
||||
this.x3 = 0.0;
|
||||
}
|
||||
|
||||
public void Conjugate()
|
||||
{
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
this.x3 = -this.x3;
|
||||
}
|
||||
|
||||
public void MakeOpposite()
|
||||
{
|
||||
this.s0 = -this.s0;
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
this.x3 = -this.x3;
|
||||
}
|
||||
|
||||
public bool Invert()
|
||||
{
|
||||
double squareModulus = this.GetSquareModulus();
|
||||
|
||||
if (squareModulus <= UtilityFP64.SQUARE_EPSYLON || double.IsNaN(squareModulus))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
double multiplicand = 1.0 / squareModulus;
|
||||
|
||||
this.s0 = this.s0 * multiplicand;
|
||||
this.x1 = -this.x1 * multiplicand;
|
||||
this.x2 = -this.x2 * multiplicand;
|
||||
this.x3 = -this.x3 * multiplicand;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Normalize()
|
||||
{
|
||||
double squareModulus = this.GetSquareModulus();
|
||||
|
||||
if (squareModulus <= UtilityFP64.SQUARE_EPSYLON || double.IsNaN(squareModulus))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
double multiplier = Math.Sqrt(1.0 / squareModulus);
|
||||
|
||||
this.s0 *= multiplier;
|
||||
this.x1 *= multiplier;
|
||||
this.x2 *= multiplier;
|
||||
this.x3 *= multiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetValues(double s0, double x1, double x2, double x3)
|
||||
{
|
||||
this.s0 = s0;
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
}
|
||||
|
||||
public void SetValues(in QuaternionFP64 quaternion)
|
||||
{
|
||||
this.s0 = quaternion.s0;
|
||||
this.x1 = quaternion.x1;
|
||||
this.x2 = quaternion.x2;
|
||||
this.x3 = quaternion.x3;
|
||||
}
|
||||
|
||||
public void SetValues(in QuaternionFP32 quaternion)
|
||||
{
|
||||
this.s0 = quaternion.s0;
|
||||
this.x1 = quaternion.x1;
|
||||
this.x2 = quaternion.x2;
|
||||
this.x3 = quaternion.x3;
|
||||
}
|
||||
|
||||
public static void Reset(out QuaternionFP64 quaternion)
|
||||
{
|
||||
quaternion.s0 = 0.0;
|
||||
quaternion.x1 = 0.0;
|
||||
quaternion.x2 = 0.0;
|
||||
quaternion.x3 = 0.0;
|
||||
}
|
||||
|
||||
public static void MakeUnit(out QuaternionFP64 quaternion)
|
||||
{
|
||||
quaternion.s0 = 1.0;
|
||||
quaternion.x1 = 0.0;
|
||||
quaternion.x2 = 0.0;
|
||||
quaternion.x3 = 0.0;
|
||||
}
|
||||
|
||||
public static void Swap(ref QuaternionFP64 quaternion1, ref QuaternionFP64 quaternion2)
|
||||
{
|
||||
double s0 = quaternion1.s0;
|
||||
double x1 = quaternion1.x1;
|
||||
double x2 = quaternion1.x2;
|
||||
double x3 = quaternion1.x3;
|
||||
|
||||
quaternion1.s0 = quaternion2.s0;
|
||||
quaternion1.x1 = quaternion2.x1;
|
||||
quaternion1.x2 = quaternion2.x2;
|
||||
quaternion1.x3 = quaternion2.x3;
|
||||
|
||||
quaternion2.s0 = s0;
|
||||
quaternion2.x1 = x1;
|
||||
quaternion2.x2 = x2;
|
||||
quaternion2.x3 = x3;
|
||||
}
|
||||
|
||||
public static void Add(in QuaternionFP64 quaternion1, in QuaternionFP64 quaternion2, out QuaternionFP64 sum)
|
||||
{
|
||||
sum.s0 = quaternion1.s0 + quaternion2.s0;
|
||||
sum.x1 = quaternion1.x1 + quaternion2.x1;
|
||||
sum.x2 = quaternion1.x2 + quaternion2.x2;
|
||||
sum.x3 = quaternion1.x3 + quaternion2.x3;
|
||||
}
|
||||
|
||||
public static void AddScaled(in QuaternionFP64 basic_quaternion, in QuaternionFP64 scalable_quaternion, double scale, out QuaternionFP64 sum)
|
||||
{
|
||||
sum.s0 = basic_quaternion.s0 + scale * scalable_quaternion.s0;
|
||||
sum.x1 = basic_quaternion.x1 + scale * scalable_quaternion.x1;
|
||||
sum.x2 = basic_quaternion.x2 + scale * scalable_quaternion.x2;
|
||||
sum.x3 = basic_quaternion.x3 + scale * scalable_quaternion.x3;
|
||||
}
|
||||
|
||||
public static void Subtract(in QuaternionFP64 minuend, in QuaternionFP64 subtrahend, out QuaternionFP64 difference)
|
||||
{
|
||||
difference.s0 = minuend.s0 - subtrahend.s0;
|
||||
difference.x1 = minuend.x1 - subtrahend.x1;
|
||||
difference.x2 = minuend.x2 - subtrahend.x2;
|
||||
difference.x3 = minuend.x3 - subtrahend.x3;
|
||||
}
|
||||
|
||||
public static void Multiply(in QuaternionFP64 left, in QuaternionFP64 right, out QuaternionFP64 product)
|
||||
{
|
||||
double s0 = left.s0 * right.s0 - left.x1 * right.x1 - (left.x2 * right.x2 + left.x3 * right.x3);
|
||||
double x1 = left.x1 * right.s0 + left.s0 * right.x1 - (left.x3 * right.x2 - left.x2 * right.x3);
|
||||
double x2 = left.x2 * right.s0 + left.s0 * right.x2 - (left.x1 * right.x3 - left.x3 * right.x1);
|
||||
double x3 = left.x3 * right.s0 + left.s0 * right.x3 - (left.x2 * right.x1 - left.x1 * right.x2);
|
||||
|
||||
product.s0 = s0;
|
||||
product.x1 = x1;
|
||||
product.x2 = x2;
|
||||
product.x3 = x3;
|
||||
}
|
||||
|
||||
public static void Multiply(in QuaternionFP64 quaternion, double multiplier, out QuaternionFP64 product)
|
||||
{
|
||||
product.s0 = quaternion.s0 * multiplier;
|
||||
product.x1 = quaternion.x1 * multiplier;
|
||||
product.x2 = quaternion.x2 * multiplier;
|
||||
product.x3 = quaternion.x3 * multiplier;
|
||||
}
|
||||
|
||||
public static bool Divide(in QuaternionFP64 divident, in QuaternionFP64 divisor, out QuaternionFP64 quotient)
|
||||
{
|
||||
double squareModulus = divisor.GetSquareModulus();
|
||||
|
||||
if (squareModulus <= UtilityFP64.SQUARE_EPSYLON || double.IsNaN(squareModulus))
|
||||
{
|
||||
Reset(out quotient);
|
||||
return false;
|
||||
}
|
||||
|
||||
double s0 = (divident.s0 * divisor.s0 + divident.x1 * divisor.x1) + (divident.x2 * divisor.x2 + divident.x3 * divisor.x3);
|
||||
double x1 = (divident.x1 * divisor.s0 + divident.x3 * divisor.x2) - (divident.s0 * divisor.x1 + divident.x2 * divisor.x3);
|
||||
double x2 = (divident.x2 * divisor.s0 + divident.x1 * divisor.x3) - (divident.s0 * divisor.x2 + divident.x3 * divisor.x1);
|
||||
double x3 = (divident.x3 * divisor.s0 + divident.x2 * divisor.x1) - (divident.s0 * divisor.x3 + divident.x1 * divisor.x2);
|
||||
|
||||
double multiplicand = 1.0 / squareModulus;
|
||||
|
||||
quotient.s0 = s0 * multiplicand;
|
||||
quotient.x1 = x1 * multiplicand;
|
||||
quotient.x2 = x2 * multiplicand;
|
||||
quotient.x3 = x3 * multiplicand;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Divide(in QuaternionFP64 divident, double divisor, out QuaternionFP64 quotient)
|
||||
{
|
||||
Multiply(divident, 1.0 / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void GetMeanOfTwo(in QuaternionFP64 vector1, in QuaternionFP64 vector2, out QuaternionFP64 mean)
|
||||
{
|
||||
mean.s0 = (vector1.s0 + vector2.s0) * 0.5;
|
||||
mean.x1 = (vector1.x1 + vector2.x1) * 0.5;
|
||||
mean.x2 = (vector1.x2 + vector2.x2) * 0.5;
|
||||
mean.x3 = (vector1.x3 + vector2.x3) * 0.5;
|
||||
}
|
||||
|
||||
public static void GetMeanOfThree(in QuaternionFP64 vector1, in QuaternionFP64 vector2, in QuaternionFP64 vector3, out QuaternionFP64 mean)
|
||||
{
|
||||
mean.s0 = (vector1.s0 + vector2.s0 + vector3.s0) * UtilityFP64.ONE_THIRD;
|
||||
mean.x1 = (vector1.x1 + vector2.x1 + vector3.x1) * UtilityFP64.ONE_THIRD;
|
||||
mean.x2 = (vector1.x2 + vector2.x2 + vector3.x2) * UtilityFP64.ONE_THIRD;
|
||||
mean.x3 = (vector1.x3 + vector2.x3 + vector3.x3) * UtilityFP64.ONE_THIRD;
|
||||
}
|
||||
|
||||
public static void Interpolate(in QuaternionFP64 quaternion1, in QuaternionFP64 quaternion2, double phase, out QuaternionFP64 interpolation)
|
||||
{
|
||||
double counterphase = 1.0 - phase;
|
||||
|
||||
interpolation.s0 = quaternion1.s0 * counterphase + quaternion2.s0 * phase;
|
||||
interpolation.x1 = quaternion1.x1 * counterphase + quaternion2.x1 * phase;
|
||||
interpolation.x2 = quaternion1.x2 * counterphase + quaternion2.x2 * phase;
|
||||
interpolation.x3 = quaternion1.x3 * counterphase + quaternion2.x3 * phase;
|
||||
}
|
||||
|
||||
public static void GetConjugate(in QuaternionFP64 quaternion, out QuaternionFP64 conjugate)
|
||||
{
|
||||
conjugate.s0 = quaternion.s0;
|
||||
conjugate.x1 = -quaternion.x1;
|
||||
conjugate.x2 = -quaternion.x2;
|
||||
conjugate.x3 = -quaternion.x3;
|
||||
}
|
||||
|
||||
public static void GetOpposite(in QuaternionFP64 quaternion, out QuaternionFP64 opposit)
|
||||
{
|
||||
opposit.s0 = -quaternion.s0;
|
||||
opposit.x1 = -quaternion.x1;
|
||||
opposit.x2 = -quaternion.x2;
|
||||
opposit.x3 = -quaternion.x3;
|
||||
}
|
||||
|
||||
public static bool GetInverse(in QuaternionFP64 quaternion, out QuaternionFP64 inverse)
|
||||
{
|
||||
double squareModulus = quaternion.GetSquareModulus();
|
||||
|
||||
if (squareModulus <= UtilityFP64.SQUARE_EPSYLON || double.IsNaN(squareModulus))
|
||||
{
|
||||
Reset(out inverse);
|
||||
return false;
|
||||
}
|
||||
|
||||
double multiplicand = 1.0 / squareModulus;
|
||||
|
||||
inverse.s0 = quaternion.s0 * multiplicand;
|
||||
inverse.x1 = -quaternion.x1 * multiplicand;
|
||||
inverse.x2 = -quaternion.x2 * multiplicand;
|
||||
inverse.x3 = -quaternion.x3 * multiplicand;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool GetNormalized(in QuaternionFP64 quaternion, out QuaternionFP64 normalized)
|
||||
{
|
||||
double squareModulus = quaternion.GetSquareModulus();
|
||||
|
||||
if (squareModulus <= UtilityFP64.SQUARE_EPSYLON || double.IsNaN(squareModulus))
|
||||
{
|
||||
Reset(out normalized);
|
||||
return false;
|
||||
}
|
||||
|
||||
double multiplier = Math.Sqrt(1.0 / squareModulus);
|
||||
|
||||
normalized.s0 = quaternion.s0 * multiplier;
|
||||
normalized.x1 = quaternion.x1 * multiplier;
|
||||
normalized.x2 = quaternion.x2 * multiplier;
|
||||
normalized.x3 = quaternion.x3 * multiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool GetExponation(in QuaternionFP64 quaternion, double exponent, out QuaternionFP64 power)
|
||||
{
|
||||
double s0s0 = quaternion.s0 * quaternion.s0;
|
||||
double x1x1 = quaternion.x1 * quaternion.x1;
|
||||
double x2x2 = quaternion.x2 * quaternion.x2;
|
||||
double x3x3 = quaternion.x3 * quaternion.x3;
|
||||
|
||||
double squareVector = x1x1 + (x2x2 + x3x3);
|
||||
double squareModulus = (s0s0 + x1x1) + (x2x2 + x3x3);
|
||||
|
||||
if (double.IsNaN(squareModulus))
|
||||
{
|
||||
Reset(out power);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (squareModulus <= UtilityFP64.SQUARE_EPSYLON)
|
||||
{
|
||||
Reset(out power);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (squareVector <= UtilityFP64.SQUARE_EPSYLON)
|
||||
{
|
||||
if (quaternion.s0 < 0.0f)
|
||||
{
|
||||
Reset(out power);
|
||||
return false;
|
||||
}
|
||||
|
||||
power.s0 = Math.Pow(quaternion.s0, exponent);
|
||||
power.x1 = 0.0f;
|
||||
power.x2 = 0.0f;
|
||||
power.x3 = 0.0f;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
double sine = Math.Sqrt(squareVector / squareModulus);
|
||||
double power_angle = Math.Atan2(sine, quaternion.s0 / Math.Sqrt(squareModulus)) * exponent;
|
||||
double power_modulus = Math.Pow(squareModulus, 0.5f * exponent);
|
||||
double multiplier = power_modulus * Math.Sin(power_angle) / sine;
|
||||
|
||||
power.s0 = power_modulus * Math.Cos(power_angle);
|
||||
power.x1 = quaternion.x1 * multiplier;
|
||||
power.x2 = quaternion.x2 * multiplier;
|
||||
power.x3 = quaternion.x3 * multiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool GetRotationMatrix(in QuaternionFP64 quaternion, out Matrix3x3FP64 matrix)
|
||||
{
|
||||
double s0s0 = quaternion.s0 * quaternion.s0;
|
||||
double x1x1 = quaternion.x1 * quaternion.x1;
|
||||
double x2x2 = quaternion.x2 * quaternion.x2;
|
||||
double x3x3 = quaternion.x3 * quaternion.x3;
|
||||
|
||||
double squareModulus = (s0s0 + x1x1) + (x2x2 + x3x3);
|
||||
|
||||
if (squareModulus <= UtilityFP64.SQUARE_EPSYLON || !double.IsFinite(squareModulus))
|
||||
{
|
||||
Matrix3x3FP64.LoadIdentity(out matrix);
|
||||
return false;
|
||||
}
|
||||
|
||||
double corrector1 = 1.0 / squareModulus;
|
||||
|
||||
double s0x1 = quaternion.s0 * quaternion.x1;
|
||||
double s0x2 = quaternion.s0 * quaternion.x2;
|
||||
double s0x3 = quaternion.s0 * quaternion.x3;
|
||||
double x1x2 = quaternion.x1 * quaternion.x2;
|
||||
double x1x3 = quaternion.x1 * quaternion.x3;
|
||||
double x2x3 = quaternion.x2 * quaternion.x3;
|
||||
|
||||
double corrector2 = 2.0 * corrector1;
|
||||
|
||||
matrix.r1c1 = corrector1 * ((s0s0 + x1x1) - (x2x2 + x3x3));
|
||||
matrix.r2c2 = corrector1 * ((s0s0 + x2x2) - (x1x1 + x3x3));
|
||||
matrix.r3c3 = corrector1 * ((s0s0 + x3x3) - (x1x1 + x2x2));
|
||||
|
||||
matrix.r1c2 = corrector2 * (x1x2 - s0x3);
|
||||
matrix.r2c3 = corrector2 * (x2x3 - s0x1);
|
||||
matrix.r3c1 = corrector2 * (x1x3 - s0x2);
|
||||
|
||||
matrix.r2c1 = corrector2 * (x1x2 + s0x3);
|
||||
matrix.r3c2 = corrector2 * (x2x3 + s0x1);
|
||||
matrix.r1c3 = corrector2 * (x1x3 + s0x2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool GetReverseMatrix(in QuaternionFP64 quaternion, out Matrix3x3FP64 matrix)
|
||||
{
|
||||
double s0s0 = quaternion.s0 * quaternion.s0;
|
||||
double x1x1 = quaternion.x1 * quaternion.x1;
|
||||
double x2x2 = quaternion.x2 * quaternion.x2;
|
||||
double x3x3 = quaternion.x3 * quaternion.x3;
|
||||
|
||||
double squareModulus = (s0s0 + x1x1) + (x2x2 + x3x3);
|
||||
|
||||
if (squareModulus <= UtilityFP64.SQUARE_EPSYLON || !double.IsFinite(squareModulus))
|
||||
{
|
||||
Matrix3x3FP64.LoadIdentity(out matrix);
|
||||
return false;
|
||||
}
|
||||
|
||||
double corrector1 = 1.0 / squareModulus;
|
||||
|
||||
double s0x1 = quaternion.s0 * quaternion.x1;
|
||||
double s0x2 = quaternion.s0 * quaternion.x2;
|
||||
double s0x3 = quaternion.s0 * quaternion.x3;
|
||||
double x1x2 = quaternion.x1 * quaternion.x2;
|
||||
double x1x3 = quaternion.x1 * quaternion.x3;
|
||||
double x2x3 = quaternion.x2 * quaternion.x3;
|
||||
|
||||
double corrector2 = 2.0 * corrector1;
|
||||
|
||||
matrix.r1c1 = corrector1 * ((s0s0 + x1x1) - (x2x2 + x3x3));
|
||||
matrix.r2c2 = corrector1 * ((s0s0 + x2x2) - (x1x1 + x3x3));
|
||||
matrix.r3c3 = corrector1 * ((s0s0 + x3x3) - (x1x1 + x2x2));
|
||||
|
||||
matrix.r1c2 = corrector2 * (x1x2 + s0x3);
|
||||
matrix.r2c3 = corrector2 * (x2x3 + s0x1);
|
||||
matrix.r3c1 = corrector2 * (x1x3 + s0x2);
|
||||
|
||||
matrix.r2c1 = corrector2 * (x1x2 - s0x3);
|
||||
matrix.r3c2 = corrector2 * (x2x3 - s0x1);
|
||||
matrix.r1c3 = corrector2 * (x1x3 - s0x2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool GetBothMatrices(in QuaternionFP64 quaternion, out Matrix3x3FP64 matrix, out Matrix3x3FP64 reverse)
|
||||
{
|
||||
if (GetReverseMatrix(quaternion, out reverse))
|
||||
{
|
||||
Matrix3x3FP64.GetTransposed(reverse, out matrix);
|
||||
return true;
|
||||
}
|
||||
|
||||
Matrix3x3FP64.LoadIdentity(out matrix);
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool AreClose(QuaternionFP32 quaternion1, QuaternionFP32 quaternion2)
|
||||
{
|
||||
double ds0 = quaternion1.s0 - quaternion2.s0;
|
||||
double dx1 = quaternion1.x1 - quaternion2.x1;
|
||||
double dx2 = quaternion1.x2 - quaternion2.x2;
|
||||
double dx3 = quaternion1.x3 - quaternion2.x3;
|
||||
|
||||
double squareModulus1 = quaternion1.GetSquareModulus();
|
||||
double squareModulus2 = quaternion2.GetSquareModulus();
|
||||
double squareDistance = (ds0 * ds0 + dx1 * dx1) + (dx2 * dx2 + dx3 * dx3);
|
||||
|
||||
if (squareModulus1 <= UtilityFP64.EPSYLON_EFFECTIVENESS_LIMIT || squareModulus2 <= UtilityFP64.EPSYLON_EFFECTIVENESS_LIMIT) {
|
||||
return squareDistance <= UtilityFP64.SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
return squareDistance <= UtilityFP64.SQUARE_EPSYLON * squareModulus1 && squareDistance <= UtilityFP64.SQUARE_EPSYLON * squareModulus2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 2 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
{
|
||||
public struct Rotation3FP32
|
||||
{
|
||||
private float angle = 0.0f;
|
||||
|
||||
private Vector3FP32 axis;
|
||||
|
||||
public Rotation3FP32(Rotation3FP32 rotation)
|
||||
{
|
||||
this.angle = rotation.angle;
|
||||
this.axis = rotation.axis;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.angle = 0.0f;
|
||||
this.axis.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 2 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
{
|
||||
public struct Rotation3FP64
|
||||
{
|
||||
private double angle = 0.0;
|
||||
|
||||
private Vector3FP64 axis;
|
||||
|
||||
public Rotation3FP64(Rotation3FP64 rotation)
|
||||
{
|
||||
this.angle = rotation.angle;
|
||||
this.axis = rotation.axis;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.angle = 0.0;
|
||||
this.axis.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 12 Nov 2024
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
{
|
||||
public class UtilityFP32
|
||||
{
|
||||
public const float EPSYLON = 4.76837E-7f;
|
||||
public const float SQUARE_EPSYLON = EPSYLON * EPSYLON;
|
||||
|
||||
public const float EPSYLON_EFFECTIVENESS_LIMIT = 1.0f;
|
||||
|
||||
public const float ONE_THIRD = 0.333333333f;
|
||||
public const float ONE_SIXTH = 0.166666667f;
|
||||
public const float ONE_NINETH = 0.111111111f;
|
||||
|
||||
public const float GOLDEN_RATIO_HIGH = 1.618034f;
|
||||
public const float GOLDEN_RATIO_LOW = 0.618034f;
|
||||
|
||||
public static bool IsZero(float value)
|
||||
{
|
||||
return -EPSYLON <= value && value <= EPSYLON;
|
||||
}
|
||||
|
||||
public static bool IsUnit(float value)
|
||||
{
|
||||
return (1.0f - EPSYLON) <= value && value <= (1.0f + EPSYLON);
|
||||
}
|
||||
|
||||
public static bool IsSqareUnit(float square)
|
||||
{
|
||||
return (1.0f - 2.0f * EPSYLON) <= square && square <= (1.0f + 2.0f * EPSYLON);
|
||||
}
|
||||
|
||||
public static bool AreClose(float value1, float value2)
|
||||
{
|
||||
float difference = value1 - value2;
|
||||
float squareValue1 = value1 * value1;
|
||||
float squareValue2 = value2 * value2;
|
||||
float squareDifference = difference * difference;
|
||||
|
||||
if (squareValue1 <= EPSYLON_EFFECTIVENESS_LIMIT || squareValue2 <= EPSYLON_EFFECTIVENESS_LIMIT) {
|
||||
return squareDifference <= SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
return squareDifference <= SQUARE_EPSYLON * squareValue1 && squareDifference <= SQUARE_EPSYLON * squareValue2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 12 Nov 2024
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
{
|
||||
public class UtilityFP64
|
||||
{
|
||||
public const double EPSYLON = 4.996003611E-14;
|
||||
public const double SQUARE_EPSYLON = EPSYLON * EPSYLON;
|
||||
|
||||
public const double EPSYLON_EFFECTIVENESS_LIMIT = 1.0;
|
||||
|
||||
public const double ONE_THIRD = 0.333333333333333333;
|
||||
public const double ONE_SIXTH = 0.166666666666666667;
|
||||
public const double ONE_NINETH = 0.111111111111111111;
|
||||
|
||||
public const double GOLDEN_RATIO_HIGH = 1.61803398874989485;
|
||||
public const double GOLDEN_RATIO_LOW = 0.61803398874989485;
|
||||
|
||||
public static bool IsZero(double value)
|
||||
{
|
||||
return -EPSYLON <= value && value <= EPSYLON;
|
||||
}
|
||||
|
||||
public static bool IsUnit(double value)
|
||||
{
|
||||
return (1.0 - EPSYLON) <= value && value <= (1.0 + EPSYLON);
|
||||
}
|
||||
|
||||
public static bool IsSqareUnit(double square)
|
||||
{
|
||||
return (1.0 - 2.0 * EPSYLON) <= square && square <= (1.0 + 2.0 * EPSYLON);
|
||||
}
|
||||
|
||||
public static bool AreClose(double value1, double value2)
|
||||
{
|
||||
double difference = value1 - value2;
|
||||
double squareValue1 = value1 * value1;
|
||||
double squareValue2 = value2 * value2;
|
||||
double squareDifference = difference * difference;
|
||||
|
||||
if (squareValue1 <= EPSYLON_EFFECTIVENESS_LIMIT || squareValue2 <= EPSYLON_EFFECTIVENESS_LIMIT) {
|
||||
return squareDifference <= SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
return squareDifference <= SQUARE_EPSYLON * squareValue1 && squareDifference <= SQUARE_EPSYLON * squareValue2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,338 +0,0 @@
|
|||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 1 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
{
|
||||
public struct Vector2FP32
|
||||
{
|
||||
public static readonly Vector2FP32 ZERO = new Vector2FP32(0.0f, 0.0f);
|
||||
|
||||
public float x1 = 0.0f;
|
||||
public float x2 = 0.0f;
|
||||
|
||||
public Vector2FP32(float x1, float x2)
|
||||
{
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
}
|
||||
|
||||
public Vector2FP32(in Vector2FP32 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
}
|
||||
|
||||
public Vector2FP32(in Vector2FP64 vector)
|
||||
{
|
||||
this.x1 = (float)vector.x1;
|
||||
this.x2 = (float)vector.x2;
|
||||
}
|
||||
|
||||
public readonly float GetSquareModulus()
|
||||
{
|
||||
return this.x1 * this.x1 + this.x2 * this.x2;
|
||||
}
|
||||
|
||||
public readonly float GetModulus()
|
||||
{
|
||||
return MathF.Sqrt(this.GetSquareModulus());
|
||||
}
|
||||
|
||||
public readonly bool IsZero()
|
||||
{
|
||||
return this.GetSquareModulus() <= UtilityFP32.SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
public readonly bool IsUnit()
|
||||
{
|
||||
return UtilityFP32.IsSqareUnit(this.GetSquareModulus());
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.x1 = 0.0f;
|
||||
this.x2 = 0.0f;
|
||||
}
|
||||
|
||||
public void MakeOpposite()
|
||||
{
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
}
|
||||
|
||||
public readonly Vector2FP32 GetOpposite()
|
||||
{
|
||||
return new Vector2FP32(-this.x1, -this.x2);
|
||||
}
|
||||
|
||||
public bool Normalize()
|
||||
{
|
||||
float squareModulus = this.GetSquareModulus();
|
||||
|
||||
if (UtilityFP32.IsSqareUnit(squareModulus))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON || float.IsNaN(squareModulus))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float multiplier = MathF.Sqrt(1.0f / squareModulus);
|
||||
|
||||
this.x1 *= multiplier;
|
||||
this.x2 *= multiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetValues(float x1, float x2)
|
||||
{
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
}
|
||||
|
||||
public void SetValues(in Vector2FP32 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
}
|
||||
|
||||
public void SetValues(in Vector2FP64 vector)
|
||||
{
|
||||
this.x1 = (float)vector.x1;
|
||||
this.x2 = (float)vector.x2;
|
||||
}
|
||||
|
||||
public readonly override string ToString()
|
||||
{
|
||||
return String.Format("Vector2FP32({0}, {1})", this.x1, this.x2);
|
||||
}
|
||||
|
||||
public static void Swap(ref Vector2FP32 vector1, ref Vector2FP32 vector2)
|
||||
{
|
||||
float x1 = vector1.x1;
|
||||
float x2 = vector1.x2;
|
||||
|
||||
vector1.x1 = vector2.x1;
|
||||
vector1.x2 = vector2.x2;
|
||||
|
||||
vector2.x1 = x1;
|
||||
vector2.x2 = x2;
|
||||
}
|
||||
|
||||
public static void Reset(out Vector2FP32 vector)
|
||||
{
|
||||
vector.x1 = 0.0f;
|
||||
vector.x2 = 0.0f;
|
||||
}
|
||||
|
||||
public static void GetOpposite(in Vector2FP32 vector, out Vector2FP32 reverted)
|
||||
{
|
||||
reverted.x1 = -vector.x1;
|
||||
reverted.x2 = -vector.x2;
|
||||
}
|
||||
|
||||
public static bool GetNormalized(in Vector2FP32 vector, out Vector2FP32 normalized)
|
||||
{
|
||||
float squareModulus = vector.GetSquareModulus();
|
||||
|
||||
if (UtilityFP32.IsSqareUnit(squareModulus))
|
||||
{
|
||||
normalized.x1 = vector.x1;
|
||||
normalized.x2 = vector.x2;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON || float.IsNaN(squareModulus))
|
||||
{
|
||||
normalized.x1 = 0.0f;
|
||||
normalized.x2 = 0.0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
float multiplier = MathF.Sqrt(1.0f / squareModulus);
|
||||
|
||||
normalized.x1 = vector.x1 * multiplier;
|
||||
normalized.x2 = vector.x2 * multiplier;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Add(in Vector2FP32 vector1, in Vector2FP32 vector2, out Vector2FP32 sum)
|
||||
{
|
||||
sum.x1 = vector1.x1 + vector2.x1;
|
||||
sum.x2 = vector1.x2 + vector2.x2;
|
||||
}
|
||||
|
||||
public static void AddScaled(in Vector2FP32 basicVector, in Vector2FP32 scalableVector, float scale, out Vector2FP32 sum)
|
||||
{
|
||||
sum.x1 = basicVector.x1 + scalableVector.x1 * scale;
|
||||
sum.x2 = basicVector.x2 + scalableVector.x2 * scale;
|
||||
}
|
||||
|
||||
public static void Subtract(in Vector2FP32 minuend, in Vector2FP32 subtrahend, out Vector2FP32 difference)
|
||||
{
|
||||
difference.x1 = minuend.x1 - subtrahend.x1;
|
||||
difference.x2 = minuend.x2 - subtrahend.x2;
|
||||
}
|
||||
|
||||
public static void Multiply(in Vector2FP32 multiplicand, float multiplier, out Vector2FP32 product)
|
||||
{
|
||||
product.x1 = multiplicand.x1 * multiplier;
|
||||
product.x2 = multiplicand.x2 * multiplier;
|
||||
}
|
||||
|
||||
public static void Divide(in Vector2FP32 dividend, float divisor, out Vector2FP32 quotient)
|
||||
{
|
||||
Multiply(dividend, 1.0f / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void GetMeanOfTwo(in Vector2FP32 vector1, in Vector2FP32 vector2, out Vector2FP32 mean)
|
||||
{
|
||||
mean.x1 = (vector1.x1 + vector2.x1) * 0.5f;
|
||||
mean.x2 = (vector1.x2 + vector2.x2) * 0.5f;
|
||||
}
|
||||
|
||||
public static void GetMeanOfThree(in Vector2FP32 vector1, in Vector2FP32 vector2, in Vector2FP32 vector3, out Vector2FP32 mean)
|
||||
{
|
||||
mean.x1 = (vector1.x1 + vector2.x1 + vector3.x1) * UtilityFP32.ONE_THIRD;
|
||||
mean.x2 = (vector1.x2 + vector2.x2 + vector3.x2) * UtilityFP32.ONE_THIRD;
|
||||
}
|
||||
|
||||
public static void Interpolate(in Vector2FP32 vector1, in Vector2FP32 vector2, float phase, out Vector2FP32 interpolation)
|
||||
{
|
||||
float counterphase = 1.0f - phase;
|
||||
|
||||
interpolation.x1 = vector1.x1 * counterphase + vector2.x1 * phase;
|
||||
interpolation.x2 = vector1.x2 * counterphase + vector2.x2 * phase;
|
||||
}
|
||||
|
||||
public static float GetScalarProduct(in Vector2FP32 vector1, in Vector2FP32 vector2)
|
||||
{
|
||||
return vector1.x1 * vector2.x1 + vector1.x2 * vector2.x2;
|
||||
}
|
||||
|
||||
public static float GetCrossProduct(in Vector2FP32 vector1, in Vector2FP32 vector2)
|
||||
{
|
||||
return vector1.x1 * vector2.x2 - vector1.x2 * vector2.x1;
|
||||
}
|
||||
|
||||
public static float GetAngle(in Vector2FP32 vector1, in Vector2FP32 vector2, AngleUnit unit)
|
||||
{
|
||||
float squareModulus1 = vector1.GetSquareModulus();
|
||||
|
||||
if (squareModulus1 <= UtilityFP32.SQUARE_EPSYLON || float.IsNaN(squareModulus1))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float squareModulus2 = vector2.GetSquareModulus();
|
||||
|
||||
if (squareModulus2 <= UtilityFP32.SQUARE_EPSYLON || float.IsNaN(squareModulus2))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float multiplier = MathF.Sqrt(1.0f / (squareModulus1 * squareModulus2));
|
||||
|
||||
float x = GetScalarProduct(vector1, vector2);
|
||||
float y = GetCrossProduct(vector1, vector2);
|
||||
|
||||
return RadianFP32.ToUnits(MathF.Atan2(y * multiplier, x * multiplier), unit);
|
||||
}
|
||||
|
||||
public static float GetSquareDistance(in Vector2FP32 vector1, in Vector2FP32 vector2)
|
||||
{
|
||||
float dx1 = vector1.x1 - vector2.x1;
|
||||
float dx2 = vector1.x2 - vector2.x2;
|
||||
|
||||
return dx1 * dx1 + dx2 * dx2;
|
||||
}
|
||||
|
||||
public static float GetDistance(in Vector2FP32 vector1, in Vector2FP32 vector2)
|
||||
{
|
||||
return MathF.Sqrt(GetSquareDistance(vector1, vector2));
|
||||
}
|
||||
|
||||
public static bool AreCloseEnough(in Vector2FP32 vector1, in Vector2FP32 vector2, float distanceLimit)
|
||||
{
|
||||
return 0.0f <= distanceLimit && GetSquareDistance(vector1, vector2) <= distanceLimit * distanceLimit;
|
||||
}
|
||||
|
||||
public static bool AreClose(in Vector2FP32 vector1, in Vector2FP32 vector2)
|
||||
{
|
||||
float squareModulus1 = vector1.GetSquareModulus();
|
||||
float squareModulus2 = vector2.GetSquareModulus();
|
||||
float squareDistance = GetSquareDistance(vector1, vector2);
|
||||
|
||||
if (squareModulus1 <= UtilityFP32.EPSYLON_EFFECTIVENESS_LIMIT || squareModulus2 <= UtilityFP32.EPSYLON_EFFECTIVENESS_LIMIT)
|
||||
{
|
||||
return squareDistance <= UtilityFP32.SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
return squareDistance <= UtilityFP32.SQUARE_EPSYLON * squareModulus1 && squareDistance <= UtilityFP32.SQUARE_EPSYLON * squareModulus2;
|
||||
}
|
||||
|
||||
public static bool AreParallel(in Vector2FP32 vector1, in Vector2FP32 vector2)
|
||||
{
|
||||
float squareModulus1 = vector1.GetSquareModulus();
|
||||
float squareModulus2 = vector2.GetSquareModulus();
|
||||
|
||||
if (squareModulus1 <= UtilityFP32.SQUARE_EPSYLON || squareModulus2 <= UtilityFP32.SQUARE_EPSYLON)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
float crossProduct = GetCrossProduct(vector1, vector2);
|
||||
|
||||
return crossProduct * crossProduct <= UtilityFP32.SQUARE_EPSYLON * squareModulus1 * squareModulus2;
|
||||
}
|
||||
|
||||
public static bool AreOrthogonal(in Vector2FP32 vector1, in Vector2FP32 vector2)
|
||||
{
|
||||
float squareModulus1 = vector1.GetSquareModulus();
|
||||
float squareModulus2 = vector2.GetSquareModulus();
|
||||
|
||||
if (squareModulus1 <= UtilityFP32.SQUARE_EPSYLON || squareModulus2 <= UtilityFP32.SQUARE_EPSYLON)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
float scalarProduct = GetScalarProduct(vector1, vector2);
|
||||
|
||||
return scalarProduct * scalarProduct <= UtilityFP32.SQUARE_EPSYLON * squareModulus1 * squareModulus2;
|
||||
}
|
||||
|
||||
public static Attitude GetAttitude(in Vector2FP32 vector1, in Vector2FP32 vector2)
|
||||
{
|
||||
float squareModulus1 = vector1.GetSquareModulus();
|
||||
float squareModulus2 = vector2.GetSquareModulus();
|
||||
|
||||
if (squareModulus1 <= UtilityFP32.SQUARE_EPSYLON || squareModulus2 <= UtilityFP32.SQUARE_EPSYLON)
|
||||
{
|
||||
return Attitude.ZERO;
|
||||
}
|
||||
|
||||
float squareLimit = UtilityFP32.SQUARE_EPSYLON * squareModulus1 * squareModulus2;
|
||||
float scalarProduct = GetScalarProduct(vector1, vector2);
|
||||
|
||||
if (scalarProduct * scalarProduct <= squareLimit)
|
||||
{
|
||||
return Attitude.ORTHOGONAL;
|
||||
}
|
||||
|
||||
float crossProduct = GetCrossProduct(vector1, vector2);
|
||||
|
||||
if (crossProduct * crossProduct > squareLimit)
|
||||
{
|
||||
return Attitude.ANY;
|
||||
}
|
||||
|
||||
return scalarProduct > 0.0f ? Attitude.CO_DIRECTIONAL : Attitude.COUNTER_DIRECTIONAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,338 +0,0 @@
|
|||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 1 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
{
|
||||
public struct Vector2FP64
|
||||
{
|
||||
public static readonly Vector2FP64 ZERO = new Vector2FP64(0.0, 0.0);
|
||||
|
||||
public double x1 = 0.0;
|
||||
public double x2 = 0.0;
|
||||
|
||||
public Vector2FP64(double x1, double x2)
|
||||
{
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
}
|
||||
|
||||
public Vector2FP64(in Vector2FP64 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
}
|
||||
|
||||
public Vector2FP64(in Vector2FP32 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
}
|
||||
|
||||
public readonly double GetSquareModulus()
|
||||
{
|
||||
return this.x1 * this.x1 + this.x2 * this.x2;
|
||||
}
|
||||
|
||||
public readonly double GetModulus()
|
||||
{
|
||||
return Math.Sqrt(this.GetSquareModulus());
|
||||
}
|
||||
|
||||
public readonly bool IsZero()
|
||||
{
|
||||
return this.GetSquareModulus() <= UtilityFP64.SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
public readonly bool IsUnit()
|
||||
{
|
||||
return UtilityFP64.IsSqareUnit(this.GetSquareModulus());
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.x1 = 0.0;
|
||||
this.x2 = 0.0;
|
||||
}
|
||||
|
||||
public void MakeOpposite()
|
||||
{
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
}
|
||||
|
||||
public readonly Vector2FP64 GetOpposite()
|
||||
{
|
||||
return new Vector2FP64(-this.x1, -this.x2);
|
||||
}
|
||||
|
||||
public bool Normalize()
|
||||
{
|
||||
double squareModulus = this.GetSquareModulus();
|
||||
|
||||
if (UtilityFP64.IsSqareUnit(squareModulus))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (squareModulus <= UtilityFP64.SQUARE_EPSYLON || double.IsNaN(squareModulus))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
double multiplier = Math.Sqrt(1.0 / squareModulus);
|
||||
|
||||
this.x1 *= multiplier;
|
||||
this.x2 *= multiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetValues(double x1, double x2)
|
||||
{
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
}
|
||||
|
||||
public void SetValues(in Vector2FP64 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
}
|
||||
|
||||
public void SetValues(in Vector2FP32 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
}
|
||||
|
||||
public readonly override string ToString()
|
||||
{
|
||||
return String.Format("Vector2FP64({0}, {1})", this.x1, this.x2);
|
||||
}
|
||||
|
||||
public static void Swap(ref Vector2FP64 vector1, ref Vector2FP64 vector2)
|
||||
{
|
||||
double x1 = vector1.x1;
|
||||
double x2 = vector1.x2;
|
||||
|
||||
vector1.x1 = vector2.x1;
|
||||
vector1.x2 = vector2.x2;
|
||||
|
||||
vector2.x1 = x1;
|
||||
vector2.x2 = x2;
|
||||
}
|
||||
|
||||
public static void Reset(out Vector2FP64 vector)
|
||||
{
|
||||
vector.x1 = 0.0;
|
||||
vector.x2 = 0.0;
|
||||
}
|
||||
|
||||
public static void GetOpposite(in Vector2FP64 vector, out Vector2FP64 reverted)
|
||||
{
|
||||
reverted.x1 = -vector.x1;
|
||||
reverted.x2 = -vector.x2;
|
||||
}
|
||||
|
||||
public static bool GetNormalized(in Vector2FP64 vector, out Vector2FP64 normalized)
|
||||
{
|
||||
double squareModulus = vector.GetSquareModulus();
|
||||
|
||||
if (UtilityFP64.IsSqareUnit(squareModulus))
|
||||
{
|
||||
normalized.x1 = vector.x1;
|
||||
normalized.x2 = vector.x2;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (squareModulus <= UtilityFP64.SQUARE_EPSYLON || double.IsNaN(squareModulus))
|
||||
{
|
||||
normalized.x1 = 0.0;
|
||||
normalized.x2 = 0.0;
|
||||
return false;
|
||||
}
|
||||
|
||||
double multiplier = Math.Sqrt(1.0 / squareModulus);
|
||||
|
||||
normalized.x1 = vector.x1 * multiplier;
|
||||
normalized.x2 = vector.x2 * multiplier;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Add(in Vector2FP64 vector1, in Vector2FP64 vector2, out Vector2FP64 sum)
|
||||
{
|
||||
sum.x1 = vector1.x1 + vector2.x1;
|
||||
sum.x2 = vector1.x2 + vector2.x2;
|
||||
}
|
||||
|
||||
public static void AddScaled(in Vector2FP64 basicVector, in Vector2FP64 scalableVector, double scale, out Vector2FP64 sum)
|
||||
{
|
||||
sum.x1 = basicVector.x1 + scalableVector.x1 * scale;
|
||||
sum.x2 = basicVector.x2 + scalableVector.x2 * scale;
|
||||
}
|
||||
|
||||
public static void Subtract(in Vector2FP64 minuend, in Vector2FP64 subtrahend, out Vector2FP64 difference)
|
||||
{
|
||||
difference.x1 = minuend.x1 - subtrahend.x1;
|
||||
difference.x2 = minuend.x2 - subtrahend.x2;
|
||||
}
|
||||
|
||||
public static void Multiply(in Vector2FP64 multiplicand, double multiplier, out Vector2FP64 product)
|
||||
{
|
||||
product.x1 = multiplicand.x1 * multiplier;
|
||||
product.x2 = multiplicand.x2 * multiplier;
|
||||
}
|
||||
|
||||
public static void Divide(in Vector2FP64 dividend, double divisor, out Vector2FP64 quotient)
|
||||
{
|
||||
Multiply(dividend, 1.0 / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void GetMeanOfTwo(in Vector2FP64 vector1, in Vector2FP64 vector2, out Vector2FP64 mean)
|
||||
{
|
||||
mean.x1 = (vector1.x1 + vector2.x1) * 0.5;
|
||||
mean.x2 = (vector1.x2 + vector2.x2) * 0.5;
|
||||
}
|
||||
|
||||
public static void GetMeanOfThree(in Vector2FP64 vector1, in Vector2FP64 vector2, in Vector2FP64 vector3, out Vector2FP64 mean)
|
||||
{
|
||||
mean.x1 = (vector1.x1 + vector2.x1 + vector3.x1) * UtilityFP64.ONE_THIRD;
|
||||
mean.x2 = (vector1.x2 + vector2.x2 + vector3.x2) * UtilityFP64.ONE_THIRD;
|
||||
}
|
||||
|
||||
public static void Interpolate(in Vector2FP64 vector1, in Vector2FP64 vector2, double phase, out Vector2FP64 interpolation)
|
||||
{
|
||||
double counterphase = 1.0 - phase;
|
||||
|
||||
interpolation.x1 = vector1.x1 * counterphase + vector2.x1 * phase;
|
||||
interpolation.x2 = vector1.x2 * counterphase + vector2.x2 * phase;
|
||||
}
|
||||
|
||||
public static double GetScalarProduct(in Vector2FP64 vector1, in Vector2FP64 vector2)
|
||||
{
|
||||
return vector1.x1 * vector2.x1 + vector1.x2 * vector2.x2;
|
||||
}
|
||||
|
||||
public static double GetCrossProduct(in Vector2FP64 vector1, in Vector2FP64 vector2)
|
||||
{
|
||||
return vector1.x1 * vector2.x2 - vector1.x2 * vector2.x1;
|
||||
}
|
||||
|
||||
public static double GetAngle(in Vector2FP64 vector1, in Vector2FP64 vector2, AngleUnit unit)
|
||||
{
|
||||
double squareModulus1 = vector1.GetSquareModulus();
|
||||
|
||||
if (squareModulus1 <= UtilityFP64.SQUARE_EPSYLON || double.IsNaN(squareModulus1))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
double squareModulus2 = vector2.GetSquareModulus();
|
||||
|
||||
if (squareModulus2 <= UtilityFP64.SQUARE_EPSYLON || double.IsNaN(squareModulus2))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
double multiplier = Math.Sqrt(1.0 / (squareModulus1 * squareModulus2));
|
||||
|
||||
double x = GetScalarProduct(vector1, vector2);
|
||||
double y = GetCrossProduct(vector1, vector2);
|
||||
|
||||
return RadianFP64.ToUnits(Math.Atan2(y * multiplier, x * multiplier), unit);
|
||||
}
|
||||
|
||||
public static double GetSquareDistance(in Vector2FP64 vector1, in Vector2FP64 vector2)
|
||||
{
|
||||
double dx1 = vector1.x1 - vector2.x1;
|
||||
double dx2 = vector1.x2 - vector2.x2;
|
||||
|
||||
return dx1 * dx1 + dx2 * dx2;
|
||||
}
|
||||
|
||||
public static double GetDistance(in Vector2FP64 vector1, in Vector2FP64 vector2)
|
||||
{
|
||||
return Math.Sqrt(GetSquareDistance(vector1, vector2));
|
||||
}
|
||||
|
||||
public static bool AreCloseEnough(in Vector2FP64 vector1, in Vector2FP64 vector2, double distanceLimit)
|
||||
{
|
||||
return 0.0 <= distanceLimit && GetSquareDistance(vector1, vector2) <= distanceLimit * distanceLimit;
|
||||
}
|
||||
|
||||
public static bool AreClose(in Vector2FP64 vector1, in Vector2FP64 vector2)
|
||||
{
|
||||
double squareModulus1 = vector1.GetSquareModulus();
|
||||
double squareModulus2 = vector2.GetSquareModulus();
|
||||
double squareDistance = GetSquareDistance(vector1, vector2);
|
||||
|
||||
if (squareModulus1 <= UtilityFP64.EPSYLON_EFFECTIVENESS_LIMIT || squareModulus2 <= UtilityFP64.EPSYLON_EFFECTIVENESS_LIMIT)
|
||||
{
|
||||
return squareDistance <= UtilityFP64.SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
return squareDistance <= UtilityFP64.SQUARE_EPSYLON * squareModulus1 && squareDistance <= UtilityFP64.SQUARE_EPSYLON * squareModulus2;
|
||||
}
|
||||
|
||||
public static bool AreParallel(in Vector2FP64 vector1, in Vector2FP64 vector2)
|
||||
{
|
||||
double squareModulus1 = vector1.GetSquareModulus();
|
||||
double squareModulus2 = vector2.GetSquareModulus();
|
||||
|
||||
if (squareModulus1 <= UtilityFP64.SQUARE_EPSYLON || squareModulus2 <= UtilityFP64.SQUARE_EPSYLON)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
double crossProduct = GetCrossProduct(vector1, vector2);
|
||||
|
||||
return crossProduct * crossProduct <= UtilityFP64.SQUARE_EPSYLON * squareModulus1 * squareModulus2;
|
||||
}
|
||||
|
||||
public static bool AreOrthogonal(in Vector2FP64 vector1, in Vector2FP64 vector2)
|
||||
{
|
||||
double squareModulus1 = vector1.GetSquareModulus();
|
||||
double squareModulus2 = vector2.GetSquareModulus();
|
||||
|
||||
if (squareModulus1 <= UtilityFP64.SQUARE_EPSYLON || squareModulus2 <= UtilityFP64.SQUARE_EPSYLON)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
double scalarProduct = GetScalarProduct(vector1, vector2);
|
||||
|
||||
return scalarProduct * scalarProduct <= UtilityFP64.SQUARE_EPSYLON * squareModulus1 * squareModulus2;
|
||||
}
|
||||
|
||||
public static Attitude GetAttitude(in Vector2FP64 vector1, in Vector2FP64 vector2)
|
||||
{
|
||||
double squareModulus1 = vector1.GetSquareModulus();
|
||||
double squareModulus2 = vector2.GetSquareModulus();
|
||||
|
||||
if (squareModulus1 <= UtilityFP64.SQUARE_EPSYLON || squareModulus2 <= UtilityFP64.SQUARE_EPSYLON)
|
||||
{
|
||||
return Attitude.ZERO;
|
||||
}
|
||||
|
||||
double squareLimit = UtilityFP64.SQUARE_EPSYLON * squareModulus1 * squareModulus2;
|
||||
double scalarProduct = GetScalarProduct(vector1, vector2);
|
||||
|
||||
if (scalarProduct * scalarProduct <= squareLimit)
|
||||
{
|
||||
return Attitude.ORTHOGONAL;
|
||||
}
|
||||
|
||||
double crossProduct = GetCrossProduct(vector1, vector2);
|
||||
|
||||
if (crossProduct * crossProduct > squareLimit)
|
||||
{
|
||||
return Attitude.ANY;
|
||||
}
|
||||
|
||||
return scalarProduct > 0.0 ? Attitude.CO_DIRECTIONAL : Attitude.COUNTER_DIRECTIONAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,396 +0,0 @@
|
|||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 1 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
{
|
||||
public struct Vector3FP32
|
||||
{
|
||||
public static readonly Vector3FP32 ZERO = new Vector3FP32(0.0f, 0.0f, 0.0f);
|
||||
|
||||
public float x1 = 0.0f;
|
||||
public float x2 = 0.0f;
|
||||
public float x3 = 0.0f;
|
||||
|
||||
public Vector3FP32(float x1, float x2, float x3)
|
||||
{
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
}
|
||||
|
||||
public Vector3FP32(in Vector3FP32 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
this.x3 = vector.x3;
|
||||
}
|
||||
|
||||
public Vector3FP32(in Vector3FP64 vector)
|
||||
{
|
||||
this.x1 = (float)vector.x1;
|
||||
this.x2 = (float)vector.x2;
|
||||
this.x3 = (float)vector.x3;
|
||||
}
|
||||
|
||||
public readonly float GetSquareModulus()
|
||||
{
|
||||
return this.x1 * this.x1 + this.x2 * this.x2 + this.x3 * this.x3;
|
||||
}
|
||||
|
||||
public readonly float GetModulus()
|
||||
{
|
||||
return MathF.Sqrt(this.GetSquareModulus());
|
||||
}
|
||||
|
||||
public readonly bool IsZero()
|
||||
{
|
||||
return this.GetSquareModulus() <= UtilityFP32.SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
public readonly bool IsUnit()
|
||||
{
|
||||
return UtilityFP32.IsSqareUnit(this.GetSquareModulus());
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.x1 = 0.0f;
|
||||
this.x2 = 0.0f;
|
||||
this.x3 = 0.0f;
|
||||
}
|
||||
|
||||
public void MakeOpposite()
|
||||
{
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
this.x3 = -this.x3;
|
||||
}
|
||||
|
||||
public readonly Vector3FP32 GetOpposite()
|
||||
{
|
||||
return new Vector3FP32(-this.x1, -this.x2, -this.x3);
|
||||
}
|
||||
|
||||
public bool Normalize()
|
||||
{
|
||||
float squareModulus = this.GetSquareModulus();
|
||||
|
||||
if (UtilityFP32.IsSqareUnit(squareModulus))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON || float.IsNaN(squareModulus))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float multiplier = MathF.Sqrt(1.0f / squareModulus);
|
||||
|
||||
this.x1 *= multiplier;
|
||||
this.x2 *= multiplier;
|
||||
this.x3 *= multiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetValues(float x1, float x2, float x3)
|
||||
{
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
}
|
||||
|
||||
public void SetValues(in Vector3FP64 vector)
|
||||
{
|
||||
this.x1 = (float)vector.x1;
|
||||
this.x2 = (float)vector.x2;
|
||||
this.x3 = (float)vector.x3;
|
||||
}
|
||||
|
||||
public void SetValues(in Vector3FP32 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
this.x3 = vector.x3;
|
||||
}
|
||||
|
||||
public readonly override string ToString()
|
||||
{
|
||||
return String.Format("Vector3FP32({0}, {1}, {2})", this.x1, this.x2, this.x3);
|
||||
}
|
||||
|
||||
public static void Swap(ref Vector3FP32 vector1, ref Vector3FP32 vector2)
|
||||
{
|
||||
float x1 = vector1.x1;
|
||||
float x2 = vector1.x2;
|
||||
float x3 = vector1.x3;
|
||||
|
||||
vector1.x1 = vector2.x1;
|
||||
vector1.x2 = vector2.x2;
|
||||
vector1.x3 = vector2.x3;
|
||||
|
||||
vector2.x1 = x1;
|
||||
vector2.x2 = x2;
|
||||
vector2.x3 = x3;
|
||||
}
|
||||
|
||||
public static void Reset(out Vector3FP32 vector)
|
||||
{
|
||||
vector.x1 = 0.0f;
|
||||
vector.x2 = 0.0f;
|
||||
vector.x3 = 0.0f;
|
||||
}
|
||||
|
||||
public static void GetOpposite(in Vector3FP32 vector, out Vector3FP32 reverted)
|
||||
{
|
||||
reverted.x1 = -vector.x1;
|
||||
reverted.x2 = -vector.x2;
|
||||
reverted.x3 = -vector.x3;
|
||||
}
|
||||
|
||||
public static bool GetNormalized(in Vector3FP32 vector, out Vector3FP32 normalized)
|
||||
{
|
||||
float squareModulus = vector.GetSquareModulus();
|
||||
|
||||
if (UtilityFP32.IsSqareUnit(squareModulus))
|
||||
{
|
||||
normalized.x1 = vector.x1;
|
||||
normalized.x2 = vector.x2;
|
||||
normalized.x3 = vector.x3;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON || float.IsNaN(squareModulus))
|
||||
{
|
||||
normalized.x1 = 0.0f;
|
||||
normalized.x2 = 0.0f;
|
||||
normalized.x3 = 0.0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
float multiplier = MathF.Sqrt(1.0f / squareModulus);
|
||||
|
||||
normalized.x1 = vector.x1 * multiplier;
|
||||
normalized.x2 = vector.x2 * multiplier;
|
||||
normalized.x3 = vector.x3 * multiplier;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Add(in Vector3FP32 vector1, in Vector3FP32 vector2, out Vector3FP32 sum)
|
||||
{
|
||||
sum.x1 = vector1.x1 + vector2.x1;
|
||||
sum.x2 = vector1.x2 + vector2.x2;
|
||||
sum.x3 = vector1.x3 + vector2.x3;
|
||||
}
|
||||
|
||||
public static void AddScaled(in Vector3FP32 basicVector, in Vector3FP32 scalableVector, float scale, out Vector3FP32 sum)
|
||||
{
|
||||
sum.x1 = basicVector.x1 + scalableVector.x1 * scale;
|
||||
sum.x2 = basicVector.x2 + scalableVector.x2 * scale;
|
||||
sum.x3 = basicVector.x3 + scalableVector.x3 * scale;
|
||||
}
|
||||
|
||||
public static void Subtract(in Vector3FP32 minuend, in Vector3FP32 subtrahend, out Vector3FP32 difference)
|
||||
{
|
||||
difference.x1 = minuend.x1 - subtrahend.x1;
|
||||
difference.x2 = minuend.x2 - subtrahend.x2;
|
||||
difference.x3 = minuend.x3 - subtrahend.x3;
|
||||
}
|
||||
|
||||
public static void Multiply(in Vector3FP32 multiplicand, float multiplier, out Vector3FP32 product)
|
||||
{
|
||||
product.x1 = multiplicand.x1 * multiplier;
|
||||
product.x2 = multiplicand.x2 * multiplier;
|
||||
product.x3 = multiplicand.x3 * multiplier;
|
||||
}
|
||||
|
||||
public static void Divide(in Vector3FP32 dividend, float divisor, out Vector3FP32 quotient)
|
||||
{
|
||||
Multiply(dividend, 1.0f / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void GetMeanOfTwo(in Vector3FP32 vector1, in Vector3FP32 vector2, out Vector3FP32 mean)
|
||||
{
|
||||
mean.x1 = (vector1.x1 + vector2.x1) * 0.5f;
|
||||
mean.x2 = (vector1.x2 + vector2.x2) * 0.5f;
|
||||
mean.x3 = (vector1.x3 + vector2.x3) * 0.5f;
|
||||
}
|
||||
|
||||
public static void GetMeanOfThree(in Vector3FP32 vector1, in Vector3FP32 vector2, in Vector3FP32 vector3, out Vector3FP32 mean)
|
||||
{
|
||||
mean.x1 = (vector1.x1 + vector2.x1 + vector3.x1) * UtilityFP32.ONE_THIRD;
|
||||
mean.x2 = (vector1.x2 + vector2.x2 + vector3.x2) * UtilityFP32.ONE_THIRD;
|
||||
mean.x3 = (vector1.x3 + vector2.x3 + vector3.x3) * UtilityFP32.ONE_THIRD;
|
||||
}
|
||||
|
||||
public static void Interpolate(in Vector3FP32 vector1, in Vector3FP32 vector2, float phase, out Vector3FP32 interpolation)
|
||||
{
|
||||
float counterphase = 1.0f - phase;
|
||||
|
||||
interpolation.x1 = vector1.x1 * counterphase + vector2.x1 * phase;
|
||||
interpolation.x2 = vector1.x2 * counterphase + vector2.x2 * phase;
|
||||
interpolation.x3 = vector1.x3 * counterphase + vector2.x3 * phase;
|
||||
}
|
||||
|
||||
public static float GetScalarProduct(in Vector3FP32 vector1, in Vector3FP32 vector2)
|
||||
{
|
||||
return vector1.x1 * vector2.x1 + vector1.x2 * vector2.x2 + vector1.x3 * vector2.x3;
|
||||
}
|
||||
|
||||
public static float GetTripleProduct(in Vector3FP32 vector1, in Vector3FP32 vector2, in Vector3FP32 vector3)
|
||||
{
|
||||
return vector1.x1 * (vector2.x2 * vector3.x3 - vector2.x3 * vector3.x2)
|
||||
+ vector1.x2 * (vector2.x3 * vector3.x1 - vector2.x1 * vector3.x3)
|
||||
+ vector1.x3 * (vector2.x1 * vector3.x2 - vector2.x2 * vector3.x1);
|
||||
}
|
||||
|
||||
public static void GetCrossProduct(in Vector3FP32 vector1, in Vector3FP32 vector2, out Vector3FP32 product)
|
||||
{
|
||||
float x1 = vector1.x2 * vector2.x3 - vector1.x3 * vector2.x2;
|
||||
float x2 = vector1.x3 * vector2.x1 - vector1.x1 * vector2.x3;
|
||||
float x3 = vector1.x1 * vector2.x2 - vector1.x2 * vector2.x1;
|
||||
|
||||
product.x1 = x1;
|
||||
product.x2 = x2;
|
||||
product.x3 = x3;
|
||||
}
|
||||
|
||||
// [a x [b x c]] = b * (a, c) - c * (a, b)
|
||||
public static void GetDoubleCrossProduct(in Vector3FP32 vector1, in Vector3FP32 vector2, in Vector3FP32 vector3, out Vector3FP32 product)
|
||||
{
|
||||
float ac = GetScalarProduct(vector1, vector3);
|
||||
float ab = GetScalarProduct(vector1, vector2);
|
||||
|
||||
product.x1 = ac * vector2.x1 - ab * vector3.x1;
|
||||
product.x2 = ac * vector2.x2 - ab * vector3.x2;
|
||||
product.x3 = ac * vector2.x3 - ab * vector3.x3;
|
||||
}
|
||||
|
||||
public static float GetAngle(in Vector3FP32 vector1, in Vector3FP32 vector2, AngleUnit unit)
|
||||
{
|
||||
float squareModulus1 = vector1.GetSquareModulus();
|
||||
|
||||
if (squareModulus1 <= UtilityFP32.SQUARE_EPSYLON || float.IsNaN(squareModulus1))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float squareModulus2 = vector2.GetSquareModulus();
|
||||
|
||||
if (squareModulus2 <= UtilityFP32.SQUARE_EPSYLON || float.IsNaN(squareModulus2))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float multiplier = MathF.Sqrt(1.0f / (squareModulus1 * squareModulus2));
|
||||
|
||||
Vector3FP32 crossProduct;
|
||||
|
||||
GetCrossProduct(vector1, vector2, out crossProduct);
|
||||
|
||||
float x = GetScalarProduct(vector1, vector2);
|
||||
float y = crossProduct.GetModulus();
|
||||
|
||||
return RadianFP32.ToUnits(MathF.Atan2(y * multiplier, x * multiplier), unit);
|
||||
}
|
||||
|
||||
public static float GetSquareDistance(in Vector3FP32 vector1, in Vector3FP32 vector2)
|
||||
{
|
||||
float dx1 = vector1.x1 - vector2.x1;
|
||||
float dx2 = vector1.x2 - vector2.x2;
|
||||
float dx3 = vector1.x3 - vector2.x3;
|
||||
|
||||
return dx1 * dx1 + dx2 * dx2 + dx3 * dx3;
|
||||
}
|
||||
|
||||
public static float GetDistance(in Vector3FP32 vector1, in Vector3FP32 vector2)
|
||||
{
|
||||
return MathF.Sqrt(GetSquareDistance(vector1, vector2));
|
||||
}
|
||||
|
||||
public static bool AreCloseEnough(in Vector3FP32 vector1, in Vector3FP32 vector2, float distanceLimit)
|
||||
{
|
||||
return 0.0f <= distanceLimit && GetSquareDistance(vector1, vector2) <= distanceLimit * distanceLimit;
|
||||
}
|
||||
|
||||
public static bool AreClose(in Vector3FP32 vector1, in Vector3FP32 vector2)
|
||||
{
|
||||
float squareModulus1 = vector1.GetSquareModulus();
|
||||
float squareModulus2 = vector2.GetSquareModulus();
|
||||
float squareDistance = GetSquareDistance(vector1, vector2);
|
||||
|
||||
if (squareModulus1 <= UtilityFP32.EPSYLON_EFFECTIVENESS_LIMIT || squareModulus2 <= UtilityFP32.EPSYLON_EFFECTIVENESS_LIMIT)
|
||||
{
|
||||
return squareDistance <= UtilityFP32.SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
return squareDistance <= UtilityFP32.SQUARE_EPSYLON * squareModulus1 && squareDistance <= UtilityFP32.SQUARE_EPSYLON * squareModulus2;
|
||||
}
|
||||
|
||||
public static bool AreParallel(in Vector3FP32 vector1, in Vector3FP32 vector2)
|
||||
{
|
||||
float squareModulus1 = vector1.GetSquareModulus();
|
||||
float squareModulus2 = vector2.GetSquareModulus();
|
||||
|
||||
if (squareModulus1 <= UtilityFP32.SQUARE_EPSYLON || squareModulus2 <= UtilityFP32.SQUARE_EPSYLON)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Vector3FP32 crossProduct;
|
||||
|
||||
GetCrossProduct(vector1, vector2, out crossProduct);
|
||||
|
||||
return crossProduct.GetSquareModulus() <= UtilityFP32.SQUARE_EPSYLON * squareModulus1 * squareModulus2;
|
||||
}
|
||||
|
||||
public static bool AreOrthogonal(in Vector3FP32 vector1, in Vector3FP32 vector2)
|
||||
{
|
||||
float squareModulus1 = vector1.GetSquareModulus();
|
||||
float squareModulus2 = vector2.GetSquareModulus();
|
||||
|
||||
if (squareModulus1 <= UtilityFP32.SQUARE_EPSYLON || squareModulus2 <= UtilityFP32.SQUARE_EPSYLON)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
float scalarProduct = GetScalarProduct(vector1, vector2);
|
||||
|
||||
return scalarProduct * scalarProduct <= UtilityFP32.SQUARE_EPSYLON * squareModulus1 * squareModulus2;
|
||||
}
|
||||
|
||||
public static Attitude GetAttitude(in Vector3FP32 vector1, in Vector3FP32 vector2)
|
||||
{
|
||||
float squareModulus1 = vector1.GetSquareModulus();
|
||||
float squareModulus2 = vector2.GetSquareModulus();
|
||||
|
||||
if (squareModulus1 <= UtilityFP32.SQUARE_EPSYLON || squareModulus2 <= UtilityFP32.SQUARE_EPSYLON)
|
||||
{
|
||||
return Attitude.ZERO;
|
||||
}
|
||||
|
||||
float squareLimit = UtilityFP32.SQUARE_EPSYLON * squareModulus1 * squareModulus2;
|
||||
float scalarProduct = GetScalarProduct(vector1, vector2);
|
||||
|
||||
if (scalarProduct * scalarProduct <= squareLimit)
|
||||
{
|
||||
return Attitude.ORTHOGONAL;
|
||||
}
|
||||
|
||||
Vector3FP32 crossProduct;
|
||||
|
||||
GetCrossProduct(vector1, vector2, out crossProduct);
|
||||
|
||||
if (crossProduct.GetSquareModulus() > squareLimit)
|
||||
{
|
||||
return Attitude.ANY;
|
||||
}
|
||||
|
||||
return scalarProduct > 0.0f ? Attitude.CO_DIRECTIONAL : Attitude.COUNTER_DIRECTIONAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,396 +0,0 @@
|
|||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 1 Feb 2019
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
{
|
||||
public struct Vector3FP64
|
||||
{
|
||||
public static readonly Vector3FP64 ZERO = new Vector3FP64(0.0, 0.0, 0.0);
|
||||
|
||||
public double x1 = 0.0;
|
||||
public double x2 = 0.0;
|
||||
public double x3 = 0.0;
|
||||
|
||||
public Vector3FP64(double x1, double x2, double x3)
|
||||
{
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
}
|
||||
|
||||
public Vector3FP64(in Vector3FP64 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
this.x3 = vector.x3;
|
||||
}
|
||||
|
||||
public Vector3FP64(in Vector3FP32 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
this.x3 = vector.x3;
|
||||
}
|
||||
|
||||
public readonly double GetSquareModulus()
|
||||
{
|
||||
return this.x1 * this.x1 + this.x2 * this.x2 + this.x3 * this.x3;
|
||||
}
|
||||
|
||||
public readonly double GetModulus()
|
||||
{
|
||||
return Math.Sqrt(this.GetSquareModulus());
|
||||
}
|
||||
|
||||
public readonly bool IsZero()
|
||||
{
|
||||
return this.GetSquareModulus() <= UtilityFP64.SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
public readonly bool IsUnit()
|
||||
{
|
||||
return UtilityFP64.IsSqareUnit(this.GetSquareModulus());
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.x1 = 0.0;
|
||||
this.x2 = 0.0;
|
||||
this.x3 = 0.0;
|
||||
}
|
||||
|
||||
public void MakeOpposite()
|
||||
{
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
this.x3 = -this.x3;
|
||||
}
|
||||
|
||||
public readonly Vector3FP64 GetOpposite()
|
||||
{
|
||||
return new Vector3FP64(-this.x1, -this.x2, -this.x3);
|
||||
}
|
||||
|
||||
public bool Normalize()
|
||||
{
|
||||
double squareModulus = this.GetSquareModulus();
|
||||
|
||||
if (UtilityFP64.IsSqareUnit(squareModulus))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (squareModulus <= UtilityFP64.SQUARE_EPSYLON || double.IsNaN(squareModulus))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
double multiplier = Math.Sqrt(1.0 / squareModulus);
|
||||
|
||||
this.x1 *= multiplier;
|
||||
this.x2 *= multiplier;
|
||||
this.x3 *= multiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetValues(double x1, double x2, double x3)
|
||||
{
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
}
|
||||
|
||||
public void SetValues(in Vector3FP64 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
this.x3 = vector.x3;
|
||||
}
|
||||
|
||||
public void SetValues(in Vector3FP32 vector)
|
||||
{
|
||||
this.x1 = vector.x1;
|
||||
this.x2 = vector.x2;
|
||||
this.x3 = vector.x3;
|
||||
}
|
||||
|
||||
public readonly override string ToString()
|
||||
{
|
||||
return String.Format("Vector3FP64({0}, {1}, {2})", this.x1, this.x2, this.x3);
|
||||
}
|
||||
|
||||
public static void Swap(ref Vector3FP64 vector1, ref Vector3FP64 vector2)
|
||||
{
|
||||
double x1 = vector1.x1;
|
||||
double x2 = vector1.x2;
|
||||
double x3 = vector1.x3;
|
||||
|
||||
vector1.x1 = vector2.x1;
|
||||
vector1.x2 = vector2.x2;
|
||||
vector1.x3 = vector2.x3;
|
||||
|
||||
vector2.x1 = x1;
|
||||
vector2.x2 = x2;
|
||||
vector2.x3 = x3;
|
||||
}
|
||||
|
||||
public static void Reset(out Vector3FP64 vector)
|
||||
{
|
||||
vector.x1 = 0.0;
|
||||
vector.x2 = 0.0;
|
||||
vector.x3 = 0.0;
|
||||
}
|
||||
|
||||
public static void GetOpposite(in Vector3FP64 vector, out Vector3FP64 reverted)
|
||||
{
|
||||
reverted.x1 = -vector.x1;
|
||||
reverted.x2 = -vector.x2;
|
||||
reverted.x3 = -vector.x3;
|
||||
}
|
||||
|
||||
public static bool GetNormalized(in Vector3FP64 vector, out Vector3FP64 normalized)
|
||||
{
|
||||
double squareModulus = vector.GetSquareModulus();
|
||||
|
||||
if (UtilityFP64.IsSqareUnit(squareModulus))
|
||||
{
|
||||
normalized.x1 = vector.x1;
|
||||
normalized.x2 = vector.x2;
|
||||
normalized.x3 = vector.x3;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (squareModulus <= UtilityFP64.SQUARE_EPSYLON || double.IsNaN(squareModulus))
|
||||
{
|
||||
normalized.x1 = 0.0;
|
||||
normalized.x2 = 0.0;
|
||||
normalized.x3 = 0.0;
|
||||
return false;
|
||||
}
|
||||
|
||||
double multiplier = Math.Sqrt(1.0 / squareModulus);
|
||||
|
||||
normalized.x1 = vector.x1 * multiplier;
|
||||
normalized.x2 = vector.x2 * multiplier;
|
||||
normalized.x3 = vector.x3 * multiplier;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Add(in Vector3FP64 vector1, in Vector3FP64 vector2, out Vector3FP64 sum)
|
||||
{
|
||||
sum.x1 = vector1.x1 + vector2.x1;
|
||||
sum.x2 = vector1.x2 + vector2.x2;
|
||||
sum.x3 = vector1.x3 + vector2.x3;
|
||||
}
|
||||
|
||||
public static void AddScaled(in Vector3FP64 basicVector, in Vector3FP64 scalableVector, double scale, out Vector3FP64 sum)
|
||||
{
|
||||
sum.x1 = basicVector.x1 + scalableVector.x1 * scale;
|
||||
sum.x2 = basicVector.x2 + scalableVector.x2 * scale;
|
||||
sum.x3 = basicVector.x3 + scalableVector.x3 * scale;
|
||||
}
|
||||
|
||||
public static void Subtract(in Vector3FP64 minuend, in Vector3FP64 subtrahend, out Vector3FP64 difference)
|
||||
{
|
||||
difference.x1 = minuend.x1 - subtrahend.x1;
|
||||
difference.x2 = minuend.x2 - subtrahend.x2;
|
||||
difference.x3 = minuend.x3 - subtrahend.x3;
|
||||
}
|
||||
|
||||
public static void Multiply(in Vector3FP64 multiplicand, double multiplier, out Vector3FP64 product)
|
||||
{
|
||||
product.x1 = multiplicand.x1 * multiplier;
|
||||
product.x2 = multiplicand.x2 * multiplier;
|
||||
product.x3 = multiplicand.x3 * multiplier;
|
||||
}
|
||||
|
||||
public static void Divide(in Vector3FP64 dividend, double divisor, out Vector3FP64 quotient)
|
||||
{
|
||||
Multiply(dividend, 1.0 / divisor, out quotient);
|
||||
}
|
||||
|
||||
public static void GetMeanOfTwo(in Vector3FP64 vector1, in Vector3FP64 vector2, out Vector3FP64 mean)
|
||||
{
|
||||
mean.x1 = (vector1.x1 + vector2.x1) * 0.5;
|
||||
mean.x2 = (vector1.x2 + vector2.x2) * 0.5;
|
||||
mean.x3 = (vector1.x3 + vector2.x3) * 0.5;
|
||||
}
|
||||
|
||||
public static void GetMeanOfThree(in Vector3FP64 vector1, in Vector3FP64 vector2, in Vector3FP64 vector3, out Vector3FP64 mean)
|
||||
{
|
||||
mean.x1 = (vector1.x1 + vector2.x1 + vector3.x1) * UtilityFP64.ONE_THIRD;
|
||||
mean.x2 = (vector1.x2 + vector2.x2 + vector3.x2) * UtilityFP64.ONE_THIRD;
|
||||
mean.x3 = (vector1.x3 + vector2.x3 + vector3.x3) * UtilityFP64.ONE_THIRD;
|
||||
}
|
||||
|
||||
public static void Interpolate(in Vector3FP64 vector1, in Vector3FP64 vector2, double phase, out Vector3FP64 interpolation)
|
||||
{
|
||||
double counterphase = 1.0 - phase;
|
||||
|
||||
interpolation.x1 = vector1.x1 * counterphase + vector2.x1 * phase;
|
||||
interpolation.x2 = vector1.x2 * counterphase + vector2.x2 * phase;
|
||||
interpolation.x3 = vector1.x3 * counterphase + vector2.x3 * phase;
|
||||
}
|
||||
|
||||
public static double GetScalarProduct(in Vector3FP64 vector1, in Vector3FP64 vector2)
|
||||
{
|
||||
return vector1.x1 * vector2.x1 + vector1.x2 * vector2.x2 + vector1.x3 * vector2.x3;
|
||||
}
|
||||
|
||||
public static double GetTripleProduct(in Vector3FP64 vector1, in Vector3FP64 vector2, in Vector3FP64 vector3)
|
||||
{
|
||||
return vector1.x1 * (vector2.x2 * vector3.x3 - vector2.x3 * vector3.x2)
|
||||
+ vector1.x2 * (vector2.x3 * vector3.x1 - vector2.x1 * vector3.x3)
|
||||
+ vector1.x3 * (vector2.x1 * vector3.x2 - vector2.x2 * vector3.x1);
|
||||
}
|
||||
|
||||
public static void GetCrossProduct(in Vector3FP64 vector1, in Vector3FP64 vector2, out Vector3FP64 result)
|
||||
{
|
||||
double x1 = vector1.x2 * vector2.x3 - vector1.x3 * vector2.x2;
|
||||
double x2 = vector1.x3 * vector2.x1 - vector1.x1 * vector2.x3;
|
||||
double x3 = vector1.x1 * vector2.x2 - vector1.x2 * vector2.x1;
|
||||
|
||||
result.x1 = x1;
|
||||
result.x2 = x2;
|
||||
result.x3 = x3;
|
||||
}
|
||||
|
||||
// [a x [b x c]] = b * (a, c) - c * (a, b)
|
||||
public static void GetDoubleCrossProduct(in Vector3FP64 vector1, in Vector3FP64 vector2, in Vector3FP64 vector3, out Vector3FP64 product)
|
||||
{
|
||||
double ac = GetScalarProduct(vector1, vector3);
|
||||
double ab = GetScalarProduct(vector1, vector2);
|
||||
|
||||
product.x1 = ac * vector2.x1 - ab * vector3.x1;
|
||||
product.x2 = ac * vector2.x2 - ab * vector3.x2;
|
||||
product.x3 = ac * vector2.x3 - ab * vector3.x3;
|
||||
}
|
||||
|
||||
public static double GetAngle(in Vector3FP64 vector1, in Vector3FP64 vector2, AngleUnit unit)
|
||||
{
|
||||
double squareModulus1 = vector1.GetSquareModulus();
|
||||
|
||||
if (squareModulus1 <= UtilityFP64.SQUARE_EPSYLON || double.IsNaN(squareModulus1))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
double squareModulus2 = vector2.GetSquareModulus();
|
||||
|
||||
if (squareModulus2 <= UtilityFP64.SQUARE_EPSYLON || double.IsNaN(squareModulus2))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
double multiplier = Math.Sqrt(1.0 / (squareModulus1 * squareModulus2));
|
||||
|
||||
Vector3FP64 crossProduct;
|
||||
|
||||
GetCrossProduct(vector1, vector2, out crossProduct);
|
||||
|
||||
double x = GetScalarProduct(vector1, vector2);
|
||||
double y = crossProduct.GetModulus();
|
||||
|
||||
return RadianFP64.ToUnits(Math.Atan2(y * multiplier, x * multiplier), unit);
|
||||
}
|
||||
|
||||
public static double GetSquareDistance(in Vector3FP64 vector1, in Vector3FP64 vector2)
|
||||
{
|
||||
double dx1 = vector1.x1 - vector2.x1;
|
||||
double dx2 = vector1.x2 - vector2.x2;
|
||||
double dx3 = vector1.x3 - vector2.x3;
|
||||
|
||||
return dx1 * dx1 + dx2 * dx2 + dx3 * dx3;
|
||||
}
|
||||
|
||||
public static double GetDistance(in Vector3FP64 vector1, in Vector3FP64 vector2)
|
||||
{
|
||||
return Math.Sqrt(GetSquareDistance(vector1, vector2));
|
||||
}
|
||||
|
||||
public static bool AreCloseEnough(in Vector3FP64 vector1, in Vector3FP64 vector2, double distanceLimit)
|
||||
{
|
||||
return 0.0 <= distanceLimit && GetSquareDistance(vector1, vector2) <= distanceLimit * distanceLimit;
|
||||
}
|
||||
|
||||
public static bool AreClose(in Vector3FP64 vector1, in Vector3FP64 vector2)
|
||||
{
|
||||
double squareModulus1 = vector1.GetSquareModulus();
|
||||
double squareModulus2 = vector2.GetSquareModulus();
|
||||
double squareDistance = GetSquareDistance(vector1, vector2);
|
||||
|
||||
if (squareModulus1 <= UtilityFP64.EPSYLON_EFFECTIVENESS_LIMIT || squareModulus2 <= UtilityFP64.EPSYLON_EFFECTIVENESS_LIMIT)
|
||||
{
|
||||
return squareDistance <= UtilityFP64.SQUARE_EPSYLON;
|
||||
}
|
||||
|
||||
return squareDistance <= UtilityFP64.SQUARE_EPSYLON * squareModulus1 && squareDistance <= UtilityFP64.SQUARE_EPSYLON * squareModulus2;
|
||||
}
|
||||
|
||||
public static bool AreParallel(in Vector3FP64 vector1, in Vector3FP64 vector2)
|
||||
{
|
||||
double squareModulus1 = vector1.GetSquareModulus();
|
||||
double squareModulus2 = vector2.GetSquareModulus();
|
||||
|
||||
if (squareModulus1 <= UtilityFP64.SQUARE_EPSYLON || squareModulus2 <= UtilityFP64.SQUARE_EPSYLON)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Vector3FP64 crossProduct;
|
||||
|
||||
GetCrossProduct(vector1, vector2, out crossProduct);
|
||||
|
||||
return crossProduct.GetSquareModulus() <= UtilityFP64.SQUARE_EPSYLON * squareModulus1 * squareModulus2;
|
||||
}
|
||||
|
||||
public static bool AreOrthogonal(in Vector3FP64 vector1, in Vector3FP64 vector2)
|
||||
{
|
||||
double squareModulus1 = vector1.GetSquareModulus();
|
||||
double squareModulus2 = vector2.GetSquareModulus();
|
||||
|
||||
if (squareModulus1 <= UtilityFP64.SQUARE_EPSYLON || squareModulus2 <= UtilityFP64.SQUARE_EPSYLON)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
double scalarProduct = GetScalarProduct(vector1, vector2);
|
||||
|
||||
return scalarProduct * scalarProduct <= UtilityFP64.SQUARE_EPSYLON * squareModulus1 * squareModulus2;
|
||||
}
|
||||
|
||||
public static Attitude GetAttitude(in Vector3FP64 vector1, in Vector3FP64 vector2)
|
||||
{
|
||||
double squareModulus1 = vector1.GetSquareModulus();
|
||||
double squareModulus2 = vector2.GetSquareModulus();
|
||||
|
||||
if (squareModulus1 <= UtilityFP64.SQUARE_EPSYLON || squareModulus2 <= UtilityFP64.SQUARE_EPSYLON)
|
||||
{
|
||||
return Attitude.ZERO;
|
||||
}
|
||||
|
||||
double squareLimit = UtilityFP64.SQUARE_EPSYLON * squareModulus1 * squareModulus2;
|
||||
double scalarProduct = GetScalarProduct(vector1, vector2);
|
||||
|
||||
if (scalarProduct * scalarProduct <= squareLimit)
|
||||
{
|
||||
return Attitude.ORTHOGONAL;
|
||||
}
|
||||
|
||||
Vector3FP64 crossProduct;
|
||||
|
||||
GetCrossProduct(vector1, vector2, out crossProduct);
|
||||
|
||||
if (crossProduct.GetSquareModulus() > squareLimit)
|
||||
{
|
||||
return Attitude.ANY;
|
||||
}
|
||||
|
||||
return scalarProduct > 0.0f ? Attitude.CO_DIRECTIONAL : Attitude.COUNTER_DIRECTIONAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,348 +0,0 @@
|
|||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 20 Oct 2024
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
{
|
||||
public struct VersorFP32
|
||||
{
|
||||
private float s0 = 1.0f;
|
||||
private float x1 = 0.0f;
|
||||
private float x2 = 0.0f;
|
||||
private float x3 = 0.0f;
|
||||
|
||||
public VersorFP32(float s0, float x1, float x2, float x3)
|
||||
{
|
||||
this.s0 = s0;
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
|
||||
float squareModulus = this.s0 * this.s0 + this.x1 * this.x1 + (this.x2 * this.x2 + this.x3 * this.x3);
|
||||
|
||||
if (!UtilityFP32.IsSqareUnit(squareModulus))
|
||||
{
|
||||
this.Normalize(squareModulus);
|
||||
}
|
||||
}
|
||||
|
||||
public VersorFP32(in VersorFP32 versor)
|
||||
{
|
||||
this.s0 = versor.s0;
|
||||
this.x1 = versor.x1;
|
||||
this.x2 = versor.x2;
|
||||
this.x3 = versor.x3;
|
||||
}
|
||||
|
||||
public VersorFP32(in VersorFP64 versor)
|
||||
{
|
||||
this.s0 = (float)versor.GetScalar();
|
||||
this.x1 = (float)versor.GetX1();
|
||||
this.x2 = (float)versor.GetX2();
|
||||
this.x3 = (float)versor.GetX3();
|
||||
|
||||
float squareModulus = this.s0 * this.s0 + this.x1 * this.x1 + (this.x2 * this.x2 + this.x3 * this.x3);
|
||||
|
||||
if (!UtilityFP32.IsSqareUnit(squareModulus))
|
||||
{
|
||||
this.Normalize(squareModulus);
|
||||
}
|
||||
}
|
||||
|
||||
public readonly float GetScalar()
|
||||
{
|
||||
return this.s0;
|
||||
}
|
||||
|
||||
public readonly float GetX1()
|
||||
{
|
||||
return this.x1;
|
||||
}
|
||||
|
||||
public readonly float GetX2()
|
||||
{
|
||||
return this.x2;
|
||||
}
|
||||
|
||||
public readonly float GetX3()
|
||||
{
|
||||
return this.x3;
|
||||
}
|
||||
|
||||
public readonly float GetAngle(AngleUnit unit)
|
||||
{
|
||||
if (this.s0 <= -(1.0f - UtilityFP32.EPSYLON) || 1.0f - UtilityFP32.EPSYLON <= this.s0) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (UtilityFP32.IsZero(this.s0))
|
||||
{
|
||||
return AngleFP32.GetHalfCircle(unit);
|
||||
}
|
||||
|
||||
return RadianFP32.ToUnits(2.0f * MathF.Acos(this.s0), unit);
|
||||
}
|
||||
|
||||
public readonly bool IsIdle()
|
||||
{
|
||||
return this.s0 <= -(1.0f - UtilityFP32.EPSYLON) || (1.0f - UtilityFP32.EPSYLON) <= this.s0;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.s0 = 1.0f;
|
||||
this.x1 = 0.0f;
|
||||
this.x2 = 0.0f;
|
||||
this.x3 = 0.0f;
|
||||
}
|
||||
|
||||
public void MakeOpposite()
|
||||
{
|
||||
this.s0 = -this.s0;
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
this.x3 = -this.x3;
|
||||
}
|
||||
|
||||
public void Shorten()
|
||||
{
|
||||
if (this.s0 < 0.0f)
|
||||
{
|
||||
this.s0 = -this.s0;
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
this.x3 = -this.x3;
|
||||
}
|
||||
}
|
||||
|
||||
public void Invert()
|
||||
{
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
this.x3 = -this.x3;
|
||||
}
|
||||
|
||||
public void SetValues(float s0, float x1, float x2, float x3)
|
||||
{
|
||||
this.s0 = s0;
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
|
||||
float squareModulus = (s0 * s0 + x1 * x1) + (x2 * x2 + x3 * x3);
|
||||
|
||||
if (!UtilityFP32.IsSqareUnit(squareModulus))
|
||||
{
|
||||
this.Normalize(squareModulus);
|
||||
}
|
||||
}
|
||||
|
||||
public void Set(in VersorFP32 versor)
|
||||
{
|
||||
this.s0 = versor.s0;
|
||||
this.x1 = versor.x1;
|
||||
this.x2 = versor.x2;
|
||||
this.x3 = versor.x3;
|
||||
}
|
||||
|
||||
public void Set(in VersorFP64 versor)
|
||||
{
|
||||
this.SetValues((float) versor.GetScalar(), (float) versor.GetX1(), (float) versor.GetX2(), (float) versor.GetX3());
|
||||
}
|
||||
|
||||
private void Normalize(float squareModulus)
|
||||
{
|
||||
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON || !float.IsFinite(squareModulus))
|
||||
{
|
||||
this.Reset();
|
||||
return;
|
||||
}
|
||||
|
||||
float multiplier = MathF.Sqrt(1.0f / squareModulus);
|
||||
|
||||
this.s0 *= multiplier;
|
||||
this.x1 *= multiplier;
|
||||
this.x2 *= multiplier;
|
||||
this.x3 *= multiplier;
|
||||
}
|
||||
|
||||
public static void Combine(in VersorFP32 second, in VersorFP32 first, out VersorFP32 result)
|
||||
{
|
||||
LoadValues(
|
||||
(second.s0 * first.s0 - second.x1 * first.x1) - (second.x2 * first.x2 + second.x3 * first.x3),
|
||||
(second.x1 * first.s0 + second.s0 * first.x1) - (second.x3 * first.x2 - second.x2 * first.x3),
|
||||
(second.x2 * first.s0 + second.s0 * first.x2) - (second.x1 * first.x3 - second.x3 * first.x1),
|
||||
(second.x3 * first.s0 + second.s0 * first.x3) - (second.x2 * first.x1 - second.x1 * first.x2),
|
||||
out result
|
||||
);
|
||||
}
|
||||
|
||||
public static void Combine(in VersorFP32 third, in VersorFP32 second, in VersorFP32 first, out VersorFP32 result)
|
||||
{
|
||||
float s0 = (second.s0 * first.s0 - second.x1 * first.x1) - (second.x2 * first.x2 + second.x3 * first.x3);
|
||||
float x1 = (second.x1 * first.s0 + second.s0 * first.x1) - (second.x3 * first.x2 - second.x2 * first.x3);
|
||||
float x2 = (second.x2 * first.s0 + second.s0 * first.x2) - (second.x1 * first.x3 - second.x3 * first.x1);
|
||||
float x3 = (second.x3 * first.s0 + second.s0 * first.x3) - (second.x2 * first.x1 - second.x1 * first.x2);
|
||||
|
||||
LoadValues(
|
||||
(third.s0 * s0 - third.x1 * x1) - (third.x2 * x2 + third.x3 * x3),
|
||||
(third.x1 * s0 + third.s0 * x1) - (third.x3 * x2 - third.x2 * x3),
|
||||
(third.x2 * s0 + third.s0 * x2) - (third.x1 * x3 - third.x3 * x1),
|
||||
(third.x3 * s0 + third.s0 * x3) - (third.x2 * x1 - third.x1 * x2),
|
||||
out result
|
||||
);
|
||||
}
|
||||
|
||||
public static void Exclude(in VersorFP32 basic, in VersorFP32 excludant, out VersorFP32 result)
|
||||
{
|
||||
LoadValues(
|
||||
(basic.s0 * excludant.s0 + basic.x1 * excludant.x1) + (basic.x2 * excludant.x2 + basic.x3 * excludant.x3),
|
||||
(basic.x1 * excludant.s0 + basic.x3 * excludant.x2) - (basic.s0 * excludant.x1 + basic.x2 * excludant.x3),
|
||||
(basic.x2 * excludant.s0 + basic.x1 * excludant.x3) - (basic.s0 * excludant.x2 + basic.x3 * excludant.x1),
|
||||
(basic.x3 * excludant.s0 + basic.x2 * excludant.x1) - (basic.s0 * excludant.x3 + basic.x1 * excludant.x2),
|
||||
out result
|
||||
);
|
||||
}
|
||||
|
||||
public static void GetInverted(in VersorFP32 versor, out VersorFP32 conjugate)
|
||||
{
|
||||
conjugate.s0 = versor.s0;
|
||||
conjugate.x1 = -versor.x1;
|
||||
conjugate.x2 = -versor.x2;
|
||||
conjugate.x3 = -versor.x3;
|
||||
}
|
||||
|
||||
public static void GetShortened(in VersorFP32 versor, out VersorFP32 shortened)
|
||||
{
|
||||
if (versor.s0 < 0.0f) {
|
||||
shortened.s0 = -versor.s0;
|
||||
shortened.x1 = -versor.x1;
|
||||
shortened.x2 = -versor.x2;
|
||||
shortened.x3 = -versor.x3;
|
||||
}
|
||||
else {
|
||||
shortened.s0 = versor.s0;
|
||||
shortened.x1 = versor.x1;
|
||||
shortened.x2 = versor.x2;
|
||||
shortened.x3 = versor.x3;
|
||||
}
|
||||
}
|
||||
|
||||
public static void GetRotationMatrix(in VersorFP32 versor, out Matrix3x3FP32 matrix)
|
||||
{
|
||||
float s0s0 = versor.s0 * versor.s0;
|
||||
float x1x1 = versor.x1 * versor.x1;
|
||||
float x2x2 = versor.x1 * versor.x2;
|
||||
float x3x3 = versor.x1 * versor.x3;
|
||||
|
||||
float s0x1 = versor.s0 * versor.x1;
|
||||
float s0x2 = versor.s0 * versor.x2;
|
||||
float s0x3 = versor.s0 * versor.x3;
|
||||
|
||||
float x1x2 = versor.x1 * versor.x2;
|
||||
float x1x3 = versor.x1 * versor.x3;
|
||||
float x2x3 = versor.x2 * versor.x3;
|
||||
|
||||
matrix.r1c1 = s0s0 + x1x1 - (x2x2 + x3x3);
|
||||
matrix.r2c2 = s0s0 + x2x2 - (x1x1 + x3x3);
|
||||
matrix.r3c3 = s0s0 + x3x3 - (x1x1 + x2x2);
|
||||
|
||||
matrix.r1c2 = 2.0f * (x1x2 - s0x3);
|
||||
matrix.r2c3 = 2.0f * (x2x3 - s0x1);
|
||||
matrix.r3c1 = 2.0f * (x1x3 - s0x2);
|
||||
|
||||
matrix.r2c1 = 2.0f * (x1x2 + s0x3);
|
||||
matrix.r3c2 = 2.0f * (x2x3 + s0x1);
|
||||
matrix.r1c3 = 2.0f * (x1x3 + s0x2);
|
||||
}
|
||||
|
||||
public static void GetReverseMatrix(in VersorFP32 versor, out Matrix3x3FP32 matrix)
|
||||
{
|
||||
float s0s0 = versor.s0 * versor.s0;
|
||||
float x1x1 = versor.x1 * versor.x1;
|
||||
float x2x2 = versor.x1 * versor.x2;
|
||||
float x3x3 = versor.x1 * versor.x3;
|
||||
|
||||
float s0x1 = versor.s0 * versor.x1;
|
||||
float s0x2 = versor.s0 * versor.x2;
|
||||
float s0x3 = versor.s0 * versor.x3;
|
||||
|
||||
float x1x2 = versor.x1 * versor.x2;
|
||||
float x1x3 = versor.x1 * versor.x3;
|
||||
float x2x3 = versor.x2 * versor.x3;
|
||||
|
||||
matrix.r1c1 = s0s0 + x1x1 - (x2x2 + x3x3);
|
||||
matrix.r2c2 = s0s0 + x2x2 - (x1x1 + x3x3);
|
||||
matrix.r3c3 = s0s0 + x3x3 - (x1x1 + x2x2);
|
||||
|
||||
matrix.r1c2 = 2.0f * (x1x2 + s0x3);
|
||||
matrix.r2c3 = 2.0f * (x2x3 + s0x1);
|
||||
matrix.r3c1 = 2.0f * (x1x3 + s0x2);
|
||||
|
||||
matrix.r2c1 = 2.0f * (x1x2 - s0x3);
|
||||
matrix.r3c2 = 2.0f * (x2x3 - s0x1);
|
||||
matrix.r1c3 = 2.0f * (x1x3 - s0x2);
|
||||
}
|
||||
|
||||
public static void GetBothMatrices(in VersorFP32 versor, out Matrix3x3FP32 matrix, out Matrix3x3FP32 reverse)
|
||||
{
|
||||
GetReverseMatrix(versor, out reverse);
|
||||
Matrix3x3FP32.MakeTransposed(reverse, out matrix);
|
||||
}
|
||||
|
||||
public static void Turn(in VersorFP32 versor, in Vector3FP32 vector, out Vector3FP32 result)
|
||||
{
|
||||
float tx1 = 2.0f * (versor.x2 * vector.x3 - versor.x3 * vector.x2);
|
||||
float tx2 = 2.0f * (versor.x3 * vector.x1 - versor.x1 * vector.x3);
|
||||
float tx3 = 2.0f * (versor.x1 * vector.x2 - versor.x2 * vector.x1);
|
||||
|
||||
float x1 = vector.x1 + tx1 * versor.s0 + (versor.x2 * tx3 - versor.x3 * tx2);
|
||||
float x2 = vector.x2 + tx2 * versor.s0 + (versor.x3 * tx1 - versor.x1 * tx3);
|
||||
float x3 = vector.x3 + tx3 * versor.s0 + (versor.x1 * tx2 - versor.x2 * tx1);
|
||||
|
||||
result.x1 = x1;
|
||||
result.x2 = x2;
|
||||
result.x3 = x3;
|
||||
}
|
||||
|
||||
public static void TurnBack(in VersorFP32 versor, in Vector3FP32 vector, out Vector3FP32 result)
|
||||
{
|
||||
float tx1 = 2.0f * (versor.x2 * vector.x3 - versor.x3 * vector.x2);
|
||||
float tx2 = 2.0f * (versor.x3 * vector.x1 - versor.x1 * vector.x3);
|
||||
float tx3 = 2.0f * (versor.x1 * vector.x2 - versor.x2 * vector.x1);
|
||||
|
||||
float x1 = vector.x1 - tx1 * versor.s0 + (versor.x2 * tx3 - versor.x3 * tx2);
|
||||
float x2 = vector.x2 - tx2 * versor.s0 + (versor.x3 * tx1 - versor.x1 * tx3);
|
||||
float x3 = vector.x3 - tx3 * versor.s0 + (versor.x1 * tx2 - versor.x2 * tx1);
|
||||
|
||||
result.x1 = x1;
|
||||
result.x2 = x2;
|
||||
result.x3 = x3;
|
||||
}
|
||||
|
||||
public static void Reset(out VersorFP32 result)
|
||||
{
|
||||
result.s0 = 1.0f;
|
||||
result.x1 = 0.0f;
|
||||
result.x2 = 0.0f;
|
||||
result.x3 = 0.0f;
|
||||
}
|
||||
|
||||
public static void LoadValues(float s0, float x1, float x2, float x3, out VersorFP32 result)
|
||||
{
|
||||
float squareModulus = s0 * s0 + x1 * x1 + (x2 * x2 + x3 * x3);
|
||||
|
||||
result.s0 = s0;
|
||||
result.x1 = x1;
|
||||
result.x2 = x2;
|
||||
result.x3 = x3;
|
||||
|
||||
if (!UtilityFP32.IsSqareUnit(squareModulus))
|
||||
{
|
||||
result.Normalize(squareModulus);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,338 +0,0 @@
|
|||
/*
|
||||
* Author: Andrey Pokidov
|
||||
* License: Apache-2.0
|
||||
* Date: 20 Oct 2024
|
||||
*/
|
||||
|
||||
namespace BGC
|
||||
{
|
||||
public struct VersorFP64
|
||||
{
|
||||
private double s0 = 1.0;
|
||||
private double x1 = 0.0;
|
||||
private double x2 = 0.0;
|
||||
private double x3 = 0.0;
|
||||
|
||||
public VersorFP64(double s0, double x1, double x2, double x3)
|
||||
{
|
||||
this.s0 = s0;
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
|
||||
double squareModulus = this.s0 * this.s0 + this.x1 * this.x1 + (this.x2 * this.x2 + this.x3 * this.x3);
|
||||
|
||||
if (!UtilityFP64.IsSqareUnit(squareModulus))
|
||||
{
|
||||
this.Normalize(squareModulus);
|
||||
}
|
||||
}
|
||||
|
||||
public VersorFP64(in VersorFP64 versor)
|
||||
{
|
||||
this.s0 = versor.s0;
|
||||
this.x1 = versor.x1;
|
||||
this.x2 = versor.x2;
|
||||
this.x3 = versor.x3;
|
||||
}
|
||||
|
||||
public VersorFP64(in VersorFP32 versor)
|
||||
{
|
||||
this.s0 = versor.GetScalar();
|
||||
this.x1 = versor.GetX1();
|
||||
this.x2 = versor.GetX2();
|
||||
this.x3 = versor.GetX3();
|
||||
|
||||
double squareModulus = this.s0 * this.s0 + this.x1 * this.x1 + (this.x2 * this.x2 + this.x3 * this.x3);
|
||||
|
||||
if (!UtilityFP64.IsSqareUnit(squareModulus))
|
||||
{
|
||||
this.Normalize(squareModulus);
|
||||
}
|
||||
}
|
||||
|
||||
public readonly double GetScalar()
|
||||
{
|
||||
return this.s0;
|
||||
}
|
||||
|
||||
public readonly double GetX1()
|
||||
{
|
||||
return this.x1;
|
||||
}
|
||||
|
||||
public readonly double GetX2()
|
||||
{
|
||||
return this.x2;
|
||||
}
|
||||
|
||||
public readonly double GetX3()
|
||||
{
|
||||
return this.x3;
|
||||
}
|
||||
|
||||
public readonly double GetAngle(AngleUnit unit)
|
||||
{
|
||||
if (this.s0 <= -(1.0 - UtilityFP64.EPSYLON) || 1.0 - UtilityFP64.EPSYLON <= this.s0) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (UtilityFP64.IsZero(this.s0))
|
||||
{
|
||||
return AngleFP64.GetHalfCircle(unit);
|
||||
}
|
||||
|
||||
return RadianFP64.ToUnits(2.0 * Math.Acos(this.s0), unit);
|
||||
}
|
||||
|
||||
public readonly bool IsIdentity()
|
||||
{
|
||||
return this.s0 <= -(1.0 - UtilityFP64.EPSYLON) || (1.0 - UtilityFP64.EPSYLON) <= this.s0;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.s0 = 1.0;
|
||||
this.x1 = 0.0;
|
||||
this.x2 = 0.0;
|
||||
this.x3 = 0.0;
|
||||
}
|
||||
|
||||
public void MakeOpposite()
|
||||
{
|
||||
}
|
||||
|
||||
public void Shorten()
|
||||
{
|
||||
if (this.s0 < 0.0)
|
||||
{
|
||||
this.s0 = -this.s0;
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
this.x3 = -this.x3;
|
||||
}
|
||||
}
|
||||
|
||||
public void Invert()
|
||||
{
|
||||
this.x1 = -this.x1;
|
||||
this.x2 = -this.x2;
|
||||
this.x3 = -this.x3;
|
||||
}
|
||||
|
||||
public void SetValues(double s0, double x1, double x2, double x3)
|
||||
{
|
||||
this.s0 = s0;
|
||||
this.x1 = x1;
|
||||
this.x2 = x2;
|
||||
this.x3 = x3;
|
||||
|
||||
double squareModulus = (s0 * s0 + x1 * x1) + (x2 * x2 + x3 * x3);
|
||||
|
||||
if (!UtilityFP64.IsSqareUnit(squareModulus))
|
||||
{
|
||||
this.Normalize(squareModulus);
|
||||
}
|
||||
}
|
||||
|
||||
public void Set(in VersorFP64 versor)
|
||||
{
|
||||
this.s0 = versor.s0;
|
||||
this.x1 = versor.x1;
|
||||
this.x2 = versor.x2;
|
||||
this.x3 = versor.x3;
|
||||
}
|
||||
|
||||
public void Set(in VersorFP32 versor)
|
||||
{
|
||||
this.SetValues(versor.GetScalar(), versor.GetX1(), versor.GetX2(), versor.GetX3());
|
||||
}
|
||||
|
||||
private void Normalize(double squareModulus)
|
||||
{
|
||||
if (squareModulus <= UtilityFP64.SQUARE_EPSYLON || !double.IsFinite(squareModulus))
|
||||
{
|
||||
this.Reset();
|
||||
return;
|
||||
}
|
||||
|
||||
double multiplier = Math.Sqrt(1.0 / squareModulus);
|
||||
|
||||
this.s0 *= multiplier;
|
||||
this.x1 *= multiplier;
|
||||
this.x2 *= multiplier;
|
||||
this.x3 *= multiplier;
|
||||
}
|
||||
|
||||
public static void Combine(in VersorFP64 second, in VersorFP64 first, out VersorFP64 result)
|
||||
{
|
||||
LoadValues(
|
||||
(second.s0 * first.s0 - second.x1 * first.x1) - (second.x2 * first.x2 + second.x3 * first.x3),
|
||||
(second.x1 * first.s0 + second.s0 * first.x1) - (second.x3 * first.x2 - second.x2 * first.x3),
|
||||
(second.x2 * first.s0 + second.s0 * first.x2) - (second.x1 * first.x3 - second.x3 * first.x1),
|
||||
(second.x3 * first.s0 + second.s0 * first.x3) - (second.x2 * first.x1 - second.x1 * first.x2),
|
||||
out result
|
||||
);
|
||||
}
|
||||
|
||||
public static void Combine3(in VersorFP64 third, in VersorFP64 second, in VersorFP64 first, out VersorFP64 result)
|
||||
{
|
||||
double s0 = (second.s0 * first.s0 - second.x1 * first.x1) - (second.x2 * first.x2 + second.x3 * first.x3);
|
||||
double x1 = (second.x1 * first.s0 + second.s0 * first.x1) - (second.x3 * first.x2 - second.x2 * first.x3);
|
||||
double x2 = (second.x2 * first.s0 + second.s0 * first.x2) - (second.x1 * first.x3 - second.x3 * first.x1);
|
||||
double x3 = (second.x3 * first.s0 + second.s0 * first.x3) - (second.x2 * first.x1 - second.x1 * first.x2);
|
||||
|
||||
LoadValues(
|
||||
(third.s0 * s0 - third.x1 * x1) - (third.x2 * x2 + third.x3 * x3),
|
||||
(third.x1 * s0 + third.s0 * x1) - (third.x3 * x2 - third.x2 * x3),
|
||||
(third.x2 * s0 + third.s0 * x2) - (third.x1 * x3 - third.x3 * x1),
|
||||
(third.x3 * s0 + third.s0 * x3) - (third.x2 * x1 - third.x1 * x2),
|
||||
out result
|
||||
);
|
||||
}
|
||||
|
||||
public static void Exclude(in VersorFP64 basic, in VersorFP64 excludant, out VersorFP64 result)
|
||||
{
|
||||
LoadValues(
|
||||
(basic.s0 * excludant.s0 + basic.x1 * excludant.x1) + (basic.x2 * excludant.x2 + basic.x3 * excludant.x3),
|
||||
(basic.x1 * excludant.s0 + basic.x3 * excludant.x2) - (basic.s0 * excludant.x1 + basic.x2 * excludant.x3),
|
||||
(basic.x2 * excludant.s0 + basic.x1 * excludant.x3) - (basic.s0 * excludant.x2 + basic.x3 * excludant.x1),
|
||||
(basic.x3 * excludant.s0 + basic.x2 * excludant.x1) - (basic.s0 * excludant.x3 + basic.x1 * excludant.x2),
|
||||
out result
|
||||
);
|
||||
}
|
||||
|
||||
public static void MakeInverted(in VersorFP64 versor, out VersorFP64 conjugate)
|
||||
{
|
||||
conjugate.s0 = versor.s0;
|
||||
conjugate.x1 = -versor.x1;
|
||||
conjugate.x2 = -versor.x2;
|
||||
conjugate.x3 = -versor.x3;
|
||||
}
|
||||
|
||||
public static void MakeShortened(in VersorFP64 versor, out VersorFP64 shortened)
|
||||
{
|
||||
if (versor.s0 < 0.0) {
|
||||
shortened.s0 = -versor.s0;
|
||||
shortened.x1 = -versor.x1;
|
||||
shortened.x2 = -versor.x2;
|
||||
shortened.x3 = -versor.x3;
|
||||
}
|
||||
else {
|
||||
shortened.s0 = versor.s0;
|
||||
shortened.x1 = versor.x1;
|
||||
shortened.x2 = versor.x2;
|
||||
shortened.x3 = versor.x3;
|
||||
}
|
||||
}
|
||||
|
||||
public static void MakeRotationMatrix(in VersorFP64 versor, out Matrix3x3FP64 matrix)
|
||||
{
|
||||
double s0s0 = versor.s0 * versor.s0;
|
||||
double x1x1 = versor.x1 * versor.x1;
|
||||
double x2x2 = versor.x1 * versor.x2;
|
||||
double x3x3 = versor.x1 * versor.x3;
|
||||
|
||||
double s0x1 = versor.s0 * versor.x1;
|
||||
double s0x2 = versor.s0 * versor.x2;
|
||||
double s0x3 = versor.s0 * versor.x3;
|
||||
|
||||
double x1x2 = versor.x1 * versor.x2;
|
||||
double x1x3 = versor.x1 * versor.x3;
|
||||
double x2x3 = versor.x2 * versor.x3;
|
||||
|
||||
matrix.r1c1 = s0s0 + x1x1 - (x2x2 + x3x3);
|
||||
matrix.r2c2 = s0s0 + x2x2 - (x1x1 + x3x3);
|
||||
matrix.r3c3 = s0s0 + x3x3 - (x1x1 + x2x2);
|
||||
|
||||
matrix.r1c2 = 2.0 * (x1x2 - s0x3);
|
||||
matrix.r2c3 = 2.0 * (x2x3 - s0x1);
|
||||
matrix.r3c1 = 2.0 * (x1x3 - s0x2);
|
||||
|
||||
matrix.r2c1 = 2.0 * (x1x2 + s0x3);
|
||||
matrix.r3c2 = 2.0 * (x2x3 + s0x1);
|
||||
matrix.r1c3 = 2.0 * (x1x3 + s0x2);
|
||||
}
|
||||
|
||||
public static void MakeReverseMatrix(in VersorFP64 versor, out Matrix3x3FP64 matrix)
|
||||
{
|
||||
double s0s0 = versor.s0 * versor.s0;
|
||||
double x1x1 = versor.x1 * versor.x1;
|
||||
double x2x2 = versor.x1 * versor.x2;
|
||||
double x3x3 = versor.x1 * versor.x3;
|
||||
|
||||
double s0x1 = versor.s0 * versor.x1;
|
||||
double s0x2 = versor.s0 * versor.x2;
|
||||
double s0x3 = versor.s0 * versor.x3;
|
||||
|
||||
double x1x2 = versor.x1 * versor.x2;
|
||||
double x1x3 = versor.x1 * versor.x3;
|
||||
double x2x3 = versor.x2 * versor.x3;
|
||||
|
||||
matrix.r1c1 = s0s0 + x1x1 - (x2x2 + x3x3);
|
||||
matrix.r2c2 = s0s0 + x2x2 - (x1x1 + x3x3);
|
||||
matrix.r3c3 = s0s0 + x3x3 - (x1x1 + x2x2);
|
||||
|
||||
matrix.r1c2 = 2.0 * (x1x2 + s0x3);
|
||||
matrix.r2c3 = 2.0 * (x2x3 + s0x1);
|
||||
matrix.r3c1 = 2.0 * (x1x3 + s0x2);
|
||||
|
||||
matrix.r2c1 = 2.0 * (x1x2 - s0x3);
|
||||
matrix.r3c2 = 2.0 * (x2x3 - s0x1);
|
||||
matrix.r1c3 = 2.0 * (x1x3 - s0x2);
|
||||
}
|
||||
|
||||
public static void Turn(in VersorFP64 versor, in Vector3FP64 vector, out Vector3FP64 result)
|
||||
{
|
||||
double tx1 = 2.0 * (versor.x2 * vector.x3 - versor.x3 * vector.x2);
|
||||
double tx2 = 2.0 * (versor.x3 * vector.x1 - versor.x1 * vector.x3);
|
||||
double tx3 = 2.0 * (versor.x1 * vector.x2 - versor.x2 * vector.x1);
|
||||
|
||||
double x1 = vector.x1 + tx1 * versor.s0 + (versor.x2 * tx3 - versor.x3 * tx2);
|
||||
double x2 = vector.x2 + tx2 * versor.s0 + (versor.x3 * tx1 - versor.x1 * tx3);
|
||||
double x3 = vector.x3 + tx3 * versor.s0 + (versor.x1 * tx2 - versor.x2 * tx1);
|
||||
|
||||
result.x1 = x1;
|
||||
result.x2 = x2;
|
||||
result.x3 = x3;
|
||||
}
|
||||
|
||||
public static void TurnBack(in VersorFP64 versor, in Vector3FP64 vector, out Vector3FP64 result)
|
||||
{
|
||||
double tx1 = 2.0 * (versor.x2 * vector.x3 - versor.x3 * vector.x2);
|
||||
double tx2 = 2.0 * (versor.x3 * vector.x1 - versor.x1 * vector.x3);
|
||||
double tx3 = 2.0 * (versor.x1 * vector.x2 - versor.x2 * vector.x1);
|
||||
|
||||
double x1 = vector.x1 - tx1 * versor.s0 + (versor.x2 * tx3 - versor.x3 * tx2);
|
||||
double x2 = vector.x2 - tx2 * versor.s0 + (versor.x3 * tx1 - versor.x1 * tx3);
|
||||
double x3 = vector.x3 - tx3 * versor.s0 + (versor.x1 * tx2 - versor.x2 * tx1);
|
||||
|
||||
result.x1 = x1;
|
||||
result.x2 = x2;
|
||||
result.x3 = x3;
|
||||
}
|
||||
|
||||
public static void LoadIdentity(out VersorFP64 result)
|
||||
{
|
||||
result.s0 = 1.0;
|
||||
result.x1 = 0.0;
|
||||
result.x2 = 0.0;
|
||||
result.x3 = 0.0;
|
||||
}
|
||||
|
||||
public static void LoadValues(double s0, double x1, double x2, double x3, out VersorFP64 result)
|
||||
{
|
||||
double squareModulus = s0 * s0 + x1 * x1 + (x2 * x2 + x3 * x3);
|
||||
|
||||
result.s0 = s0;
|
||||
result.x1 = x1;
|
||||
result.x2 = x2;
|
||||
result.x3 = x3;
|
||||
|
||||
if (!UtilityFP64.IsSqareUnit(squareModulus))
|
||||
{
|
||||
result.Normalize(squareModulus);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,19 +2,18 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Numerics;
|
||||
using BGC;
|
||||
using BasicGeometry;
|
||||
|
||||
public static class Program
|
||||
{
|
||||
private static VersorFP32[] AllocateVersors(int amount)
|
||||
private static FP32Versor[] AllocateVersors(int amount)
|
||||
{
|
||||
return new VersorFP32[amount];
|
||||
return new FP32Versor[amount];
|
||||
}
|
||||
|
||||
private static VersorFP32[] MakeZeroVersors(int amount)
|
||||
private static FP32Versor[] MakeZeroVersors(int amount)
|
||||
{
|
||||
VersorFP32[] versors = AllocateVersors(amount);
|
||||
FP32Versor[] versors = AllocateVersors(amount);
|
||||
|
||||
for (int i = 0; i < amount; i++)
|
||||
{
|
||||
|
|
@ -24,15 +23,15 @@ public static class Program
|
|||
return versors;
|
||||
}
|
||||
|
||||
private static VersorFP32[] MakeRandomVersors(int amount)
|
||||
private static FP32Versor[] MakeRandomVersors(int amount)
|
||||
{
|
||||
Random randomizer = new Random(Environment.TickCount);
|
||||
|
||||
VersorFP32[] versors = AllocateVersors(amount);
|
||||
FP32Versor[] versors = AllocateVersors(amount);
|
||||
|
||||
for (int i = 0; i < amount; i++)
|
||||
{
|
||||
versors[i] = new VersorFP32(
|
||||
versors[i] = new FP32Versor(
|
||||
randomizer.NextSingle(),
|
||||
randomizer.NextSingle(),
|
||||
randomizer.NextSingle(),
|
||||
|
|
@ -43,18 +42,18 @@ public static class Program
|
|||
return versors;
|
||||
}
|
||||
|
||||
private static void PrintVersor(in VersorFP32 versor)
|
||||
private static void PrintVersor(in FP32Versor versor)
|
||||
{
|
||||
Console.WriteLine("({0}, {1}, {2}, {3})", versor.GetScalar(), versor.GetX1(), versor.GetX2(), versor.GetX3());
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
const int amount = 1000000;
|
||||
int amount = 1000000;
|
||||
|
||||
VersorFP32[] versors1 = MakeRandomVersors(amount);
|
||||
VersorFP32[] versors2 = MakeRandomVersors(amount);
|
||||
VersorFP32[] results = MakeZeroVersors(amount);
|
||||
FP32Versor[] versors1 = MakeRandomVersors(amount);
|
||||
FP32Versor[] versors2 = MakeRandomVersors(amount);
|
||||
FP32Versor[] results = MakeZeroVersors(amount);
|
||||
|
||||
long start, end;
|
||||
|
||||
|
|
@ -64,7 +63,7 @@ public static class Program
|
|||
{
|
||||
for (int i = 0; i < amount; i++)
|
||||
{
|
||||
VersorFP32.Combine(versors1[i], versors2[i], out results[i]);
|
||||
FP32Versor.Combine(versors1[i], versors2[i], out results[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
19
BasicGeometryTest/F32Vector2Test.cs
Normal file
19
BasicGeometryTest/F32Vector2Test.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using BasicGeometry;
|
||||
|
||||
namespace BasicGeometryTest
|
||||
{
|
||||
[TestClass]
|
||||
public class FP32Vector2Test
|
||||
{
|
||||
[TestMethod]
|
||||
public void TestInitialization()
|
||||
{
|
||||
FP32Vector2 vector = new FP32Vector2(1.0f, 2.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
using BGC;
|
||||
|
||||
namespace BasicGeometryTest
|
||||
{
|
||||
[TestClass]
|
||||
public class Vector2InitTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void InitVector2FP32()
|
||||
{
|
||||
Vector2FP32 vector = new Vector2FP32(1.0f, 2.0f);
|
||||
|
||||
Assert.AreEqual(vector.x1, 1.0f);
|
||||
Assert.AreEqual(vector.x2, 2.0f);
|
||||
|
||||
vector.Reset();
|
||||
|
||||
Assert.AreEqual(vector.x1, 0.0f);
|
||||
Assert.AreEqual(vector.x2, 0.0f);
|
||||
|
||||
vector.SetValues(-5.02f, -200.7f);
|
||||
|
||||
Assert.AreEqual(vector.x1, -5.02f);
|
||||
Assert.AreEqual(vector.x2, -200.7f);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void InitVector2FP64()
|
||||
{
|
||||
Vector2FP64 vector = new Vector2FP64(1.0, 2.0);
|
||||
|
||||
Assert.AreEqual(vector.x1, 1.0);
|
||||
Assert.AreEqual(vector.x2, 2.0);
|
||||
|
||||
vector.Reset();
|
||||
|
||||
Assert.AreEqual(vector.x1, 0.0);
|
||||
Assert.AreEqual(vector.x2, 0.0);
|
||||
|
||||
vector.SetValues(-5.79, -200.2);
|
||||
|
||||
Assert.AreEqual(vector.x1, -5.79);
|
||||
Assert.AreEqual(vector.x2, -200.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
using BGC;
|
||||
|
||||
namespace BasicGeometryTest.Vector2
|
||||
{
|
||||
[TestClass]
|
||||
public class Vector2IsZeroTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void IsZeroFP32()
|
||||
{
|
||||
Vector2FP32 vector = new Vector2FP32();
|
||||
|
||||
Assert.IsTrue(vector.IsZero());
|
||||
|
||||
vector.SetValues(UtilityFP32.EPSYLON * 0.75f, 0.0f);
|
||||
|
||||
Assert.IsTrue(vector.IsZero());
|
||||
|
||||
vector.SetValues(-UtilityFP32.EPSYLON * 0.5f, -UtilityFP32.EPSYLON * 0.5f);
|
||||
|
||||
Assert.IsTrue(vector.IsZero());
|
||||
|
||||
vector.SetValues(-UtilityFP32.EPSYLON * 1.25f, -UtilityFP32.EPSYLON * 1.25f);
|
||||
|
||||
Assert.IsFalse(vector.IsZero());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsZeroFP64()
|
||||
{
|
||||
Vector2FP64 vector = new Vector2FP64();
|
||||
|
||||
Assert.IsTrue(vector.IsZero());
|
||||
|
||||
vector.SetValues(UtilityFP64.EPSYLON * 0.75, 0.0);
|
||||
|
||||
Assert.IsTrue(vector.IsZero());
|
||||
|
||||
vector.SetValues(-UtilityFP64.EPSYLON * 0.5, UtilityFP64.EPSYLON * 0.5);
|
||||
|
||||
Assert.IsTrue(vector.IsZero());
|
||||
|
||||
vector.SetValues(UtilityFP64.EPSYLON * 1.25, UtilityFP64.EPSYLON * 1.25);
|
||||
|
||||
Assert.IsFalse(vector.IsZero());
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue