Skip to content

Commit a6cb97f

Browse files
committed
refactor: closestpointontwolines complexity
1 parent a33a706 commit a6cb97f

2 files changed

Lines changed: 37 additions & 18 deletions

File tree

src/FixedMathSharp/Numerics/Vector3d.cs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -783,43 +783,30 @@ public static (Vector3d, Vector3d) ClosestPointsOnTwoLines(Vector3d line1Start,
783783
Fixed64 e = Dot(v, w);
784784
Fixed64 D = a * c - b * b;
785785

786-
Fixed64 sc, tc;
787-
788-
// compute the line parameters of the two closest points
789-
if (D < Fixed64.Epsilon)
790-
{
791-
// the lines are almost parallel
792-
sc = Fixed64.Zero;
793-
tc = (b > c ? d / b : e / c); // use the largest denominator
794-
}
795-
else
796-
{
797-
sc = (b * e - c * d) / D;
798-
tc = (a * e - b * d) / D;
799-
}
786+
(Fixed64 sc, Fixed64 tc) = SolveClosestLineParameters(a, b, c, d, e, D);
800787

801788
// recompute sc if it is outside [0,1]
802789
if (sc < Fixed64.Zero)
803790
{
804791
sc = Fixed64.Zero;
805-
tc = (e < Fixed64.Zero ? Fixed64.Zero : (e > c ? Fixed64.One : e / c));
792+
tc = ClampSegmentParameter(e, c);
806793
}
807794
else if (sc > Fixed64.One)
808795
{
809796
sc = Fixed64.One;
810-
tc = (e + b < Fixed64.Zero ? Fixed64.Zero : (e + b > c ? Fixed64.One : (e + b) / c));
797+
tc = ClampSegmentParameter(e + b, c);
811798
}
812799

813800
// recompute tc if it is outside [0,1]
814801
if (tc < Fixed64.Zero)
815802
{
816803
tc = Fixed64.Zero;
817-
sc = (-d < Fixed64.Zero ? Fixed64.Zero : (-d > a ? Fixed64.One : -d / a));
804+
sc = ClampSegmentParameter(-d, a);
818805
}
819806
else if (tc > Fixed64.One)
820807
{
821808
tc = Fixed64.One;
822-
sc = ((-d + b) < Fixed64.Zero ? Fixed64.Zero : ((-d + b) > a ? Fixed64.One : (-d + b) / a));
809+
sc = ClampSegmentParameter(-d + b, a);
823810
}
824811

825812
// get the difference of the two closest points
@@ -829,6 +816,27 @@ public static (Vector3d, Vector3d) ClosestPointsOnTwoLines(Vector3d line1Start,
829816
return (pointOnLine1, pointOnLine2);
830817
}
831818

819+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
820+
private static (Fixed64 sc, Fixed64 tc) SolveClosestLineParameters(Fixed64 a, Fixed64 b, Fixed64 c, Fixed64 d, Fixed64 e, Fixed64 determinant)
821+
{
822+
if (determinant < Fixed64.Epsilon)
823+
return (Fixed64.Zero, b > c ? d / b : e / c);
824+
825+
return ((b * e - c * d) / determinant, (a * e - b * d) / determinant);
826+
}
827+
828+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
829+
private static Fixed64 ClampSegmentParameter(Fixed64 numerator, Fixed64 denominator)
830+
{
831+
if (numerator < Fixed64.Zero)
832+
return Fixed64.Zero;
833+
834+
if (numerator > denominator)
835+
return Fixed64.One;
836+
837+
return numerator / denominator;
838+
}
839+
832840
/// <summary>
833841
/// Finds the closest point on a line segment between points A and B to a given point P.
834842
/// </summary>

tests/FixedMathSharp.Tests/Vector3d.Tests.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,17 @@ public void Slerp_InterpolatesOnSphere()
441441
Assert.True(Vector3d.AreAlmostParallel(result, expected, new Fixed64(0.999)));
442442
}
443443

444+
[Fact]
445+
public void Slerp_ClampsDotProductBeforeAcos()
446+
{
447+
var start = Vector3d.Right;
448+
var end = new Vector3d(Fixed64.FromRaw(Fixed64.One.m_rawValue + 1), Fixed64.Zero, Fixed64.Zero);
449+
450+
var result = Vector3d.Slerp(start, end, Fixed64.Half);
451+
452+
Assert.Equal(start, result);
453+
}
454+
444455
[Fact]
445456
public void StaticMagnitude_CalculatesCorrectly()
446457
{

0 commit comments

Comments
 (0)