@@ -449,7 +449,30 @@ public bool IsNormalized()
449449 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
450450 public bool AllComponentsGreaterThanEpsilon ( )
451451 {
452- return x > Fixed64 . Epsilon && y > Fixed64 . Epsilon && z > Fixed64 . Epsilon ;
452+ return x . Abs ( ) > Fixed64 . Epsilon && y . Abs ( ) > Fixed64 . Epsilon && z . Abs ( ) > Fixed64 . Epsilon ;
453+ }
454+
455+ /// <summary>
456+ /// Returns a new vector with components whose absolute values are less than the specified threshold set to zero.
457+ /// </summary>
458+ /// <remarks>
459+ /// This method is useful for eliminating insignificant floating-point errors by zeroing out very small vector components.
460+ /// The default threshold is suitable for most cases where near-zero values are considered noise.
461+ /// </remarks>
462+ /// <param name="threshold">
463+ /// The minimum absolute value a component must have to be retained.
464+ /// If null, a default epsilon value is used.
465+ /// </param>
466+ /// <returns>A new Vector3d instance with small components snapped to zero based on the specified threshold.</returns>
467+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
468+ public Vector3d SnapSmallComponentsToZero ( Fixed64 ? threshold = null )
469+ {
470+ Fixed64 effectiveThreshold = threshold ?? Fixed64 . Epsilon ;
471+ return new Vector3d (
472+ x . Abs ( ) < effectiveThreshold ? Fixed64 . Zero : x ,
473+ y . Abs ( ) < effectiveThreshold ? Fixed64 . Zero : y ,
474+ z . Abs ( ) < effectiveThreshold ? Fixed64 . Zero : z
475+ ) ;
453476 }
454477
455478 /// <summary>
@@ -622,7 +645,7 @@ public static Vector3d GetNormalized(Vector3d value)
622645 return new Vector3d ( Fixed64 . Zero , Fixed64 . Zero , Fixed64 . Zero ) ;
623646
624647 // If already normalized, return as-is
625- if ( mag == Fixed64 . One )
648+ if ( FixedMath . Abs ( mag - Fixed64 . One ) <= Fixed64 . Epsilon )
626649 return value ;
627650
628651 // Normalize it exactly
@@ -643,8 +666,8 @@ public static Fixed64 GetMagnitude(Vector3d vector)
643666 {
644667 Fixed64 mag = ( vector . x * vector . x ) + ( vector . y * vector . y ) + ( vector . z * vector . z ) ;
645668
646- // If rounding error pushed magnitude slightly above 1, clamp it
647- if ( mag > Fixed64 . One && mag <= Fixed64 . One + Fixed64 . Epsilon )
669+ // Clamp tiny drift around 1 in either direction.
670+ if ( FixedMath . Abs ( mag - Fixed64 . One ) <= Fixed64 . Epsilon )
648671 return Fixed64 . One ;
649672
650673 return mag != Fixed64 . Zero ? FixedMath . Sqrt ( mag ) : Fixed64 . Zero ;
@@ -817,9 +840,15 @@ public static (Vector3d, Vector3d) ClosestPointsOnTwoLines(Vector3d line1Start,
817840 }
818841
819842 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
820- private static ( Fixed64 sc , Fixed64 tc ) SolveClosestLineParameters ( Fixed64 a , Fixed64 b , Fixed64 c , Fixed64 d , Fixed64 e , Fixed64 determinant )
843+ private static ( Fixed64 sc , Fixed64 tc ) SolveClosestLineParameters (
844+ Fixed64 a ,
845+ Fixed64 b ,
846+ Fixed64 c ,
847+ Fixed64 d ,
848+ Fixed64 e ,
849+ Fixed64 determinant )
821850 {
822- if ( determinant < Fixed64 . Epsilon )
851+ if ( determinant . Abs ( ) < Fixed64 . Epsilon )
823852 return ( Fixed64 . Zero , b > c ? d / b : e / c ) ;
824853
825854 return ( ( b * e - c * d ) / determinant , ( a * e - b * d ) / determinant ) ;
@@ -903,7 +932,7 @@ public static Fixed64 CrossProduct(Vector3d lhs, Vector3d rhs)
903932 public static Vector3d Project ( Vector3d vector , Vector3d onNormal )
904933 {
905934 Fixed64 sqrMag = Dot ( onNormal , onNormal ) ;
906- if ( sqrMag < Fixed64 . Epsilon )
935+ if ( sqrMag . Abs ( ) < Fixed64 . Epsilon )
907936 return Zero ;
908937 else
909938 {
@@ -923,7 +952,7 @@ public static Vector3d Project(Vector3d vector, Vector3d onNormal)
923952 public static Vector3d ProjectOnPlane ( Vector3d vector , Vector3d planeNormal )
924953 {
925954 Fixed64 sqrMag = Dot ( planeNormal , planeNormal ) ;
926- if ( sqrMag < Fixed64 . Epsilon )
955+ if ( sqrMag . Abs ( ) < Fixed64 . Epsilon )
927956 return vector ;
928957 else
929958 {
0 commit comments