< Summary

Information
Class: FixedMathSharp.FixedCurve
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Numerics/Curves/FixedCurve.cs
Line coverage
97%
Covered lines: 43
Uncovered lines: 1
Coverable lines: 44
Total lines: 155
Line coverage: 97.7%
Branch coverage
94%
Covered branches: 34
Total branches: 36
Branch coverage: 94.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
.ctor(...)100%88100%
Evaluate(...)87.5%161695.23%
Equals(...)100%66100%
Equals(...)100%22100%
GetHashCode()100%22100%
op_Equality(...)100%22100%
op_Inequality(...)100%11100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Numerics/Curves/FixedCurve.cs

#LineLine coverage
 1using MemoryPack;
 2using System;
 3using System.Linq;
 4using System.Text.Json.Serialization;
 5
 6namespace FixedMathSharp;
 7
 8/// <summary>
 9/// Specifies the interpolation method used when evaluating a <see cref="FixedCurve"/>.
 10/// </summary>
 11public enum FixedCurveMode
 12{
 13    /// <summary>Linear interpolation between keyframes.</summary>
 14    Linear,
 15
 16    /// <summary>Step interpolation, instantly jumping between keyframe values.</summary>
 17    Step,
 18
 19    /// <summary>Smooth interpolation using a cosine function (SmoothStep).</summary>
 20    Smooth,
 21
 22    /// <summary>Cubic interpolation for smoother curves using tangents.</summary>
 23    Cubic
 24}
 25
 26/// <summary>
 27/// A deterministic fixed-point curve that interpolates values between keyframes.
 28/// Used for animations, physics calculations, and procedural data.
 29/// </summary>
 30[Serializable]
 31[MemoryPackable]
 32public partial class FixedCurve : IEquatable<FixedCurve>
 33{
 34    #region Constructors
 35
 36    /// <summary>
 37    /// Initializes a new instance of the <see cref="FixedCurve"/> with a default linear interpolation mode.
 38    /// </summary>
 39    /// <param name="keyframes">The keyframes defining the curve.</param>
 40    public FixedCurve(params FixedCurveKey[] keyframes)
 1541        : this(FixedCurveMode.Linear, keyframes) { }
 42
 43    /// <summary>
 44    /// Initializes a new instance of the <see cref="FixedCurve"/> with a specified interpolation mode.
 45    /// </summary>
 46    /// <param name="mode">The interpolation method to use.</param>
 47    /// <param name="keyframes">The keyframes defining the curve.</param>
 48    [JsonConstructor]
 49    [MemoryPackConstructor]
 2250    public FixedCurve(FixedCurveMode mode, params FixedCurveKey[] keyframes)
 2251    {
 2252        Keyframes = keyframes?.Length > 1
 2253            ? keyframes.OrderBy(k => k.Time).ToArray()
 2254            : keyframes?.Clone() as FixedCurveKey[] ?? Array.Empty<FixedCurveKey>();
 2255        Mode = mode;
 2256    }
 57
 58    #endregion
 59
 60    #region Properties
 61
 62    /// <summary>
 63    /// Gets the mode used for the fixed curve calculation.
 64    /// </summary>
 65    [JsonInclude]
 66    [MemoryPackOrder(0)]
 67    public FixedCurveMode Mode { get; private set; }
 68
 69    /// <summary>
 70    /// Gets the collection of keyframes that define the curve.
 71    /// </summary>
 72    [JsonInclude]
 73    [MemoryPackOrder(1)]
 74    public FixedCurveKey[] Keyframes { get; private set; }
 75
 76    #endregion
 77
 78    #region Methods
 79
 80    /// <summary>
 81    /// Evaluates the curve at a given time using the specified interpolation mode.
 82    /// </summary>
 83    /// <param name="time">The time at which to evaluate the curve.</param>
 84    /// <returns>The interpolated value at the given time.</returns>
 85    public Fixed64 Evaluate(Fixed64 time)
 2386    {
 2487        if (Keyframes.Length == 0) return Fixed64.One;
 88
 89        // Clamp input within the keyframe range
 2990        if (time <= Keyframes[0].Time) return Keyframes[0].Value;
 2291        if (time >= Keyframes[^1].Time) return Keyframes[^1].Value;
 92
 93        // Find the surrounding keyframes
 2494        for (int i = 0; i < Keyframes.Length - 1; i++)
 1295        {
 1296            if (time >= Keyframes[i].Time && time < Keyframes[i + 1].Time)
 897            {
 98                // Compute interpolation factor
 899                Fixed64 t = (time - Keyframes[i].Time) / (Keyframes[i + 1].Time - Keyframes[i].Time);
 100
 101                // Choose interpolation method
 8102                return Mode switch
 8103                {
 3104                    FixedCurveMode.Step => Keyframes[i].Value,// Immediate transition
 1105                    FixedCurveMode.Smooth => FixedMath.SmoothStep(Keyframes[i].Value, Keyframes[i + 1].Value, t),
 1106                    FixedCurveMode.Cubic => FixedMath.CubicInterpolate(
 1107                                                    Keyframes[i].Value, Keyframes[i + 1].Value,
 1108                                                    Keyframes[i].OutTangent, Keyframes[i + 1].InTangent, t),
 3109                    _ => FixedMath.LinearInterpolate(Keyframes[i].Value, Keyframes[i + 1].Value, t),
 8110                };
 111            }
 4112        }
 113
 0114        return Fixed64.One; // Fallback (should never be hit)
 23115    }
 116
 117    #endregion
 118
 119    #region Equality
 120
 121    /// <inheritdoc/>
 122    public bool Equals(FixedCurve? other)
 11123    {
 14124        if (other is null) return false;
 9125        if (ReferenceEquals(this, other)) return true;
 7126        return Mode == other.Mode && Keyframes.SequenceEqual(other.Keyframes);
 11127    }
 128
 129    /// <inheritdoc/>
 2130    public override bool Equals(object? obj) => obj is FixedCurve other && Equals(other);
 131
 132    /// <inheritdoc/>
 133    public override int GetHashCode()
 2134    {
 135        unchecked
 2136        {
 2137            int hash = (int)Mode;
 14138            foreach (var key in Keyframes)
 4139                hash = (hash * 31) ^ key.GetHashCode();
 2140            return hash;
 141        }
 2142    }
 143
 144    /// <summary>
 145    /// Determines whether two FixedCurve instances are equal.
 146    /// </summary>
 7147    public static bool operator ==(FixedCurve? left, FixedCurve? right) => left?.Equals(right) ?? right is null;
 148
 149    /// <summary>
 150    /// Determines whether two FixedCurve instances are not equal.
 151    /// </summary>
 2152    public static bool operator !=(FixedCurve? left, FixedCurve? right) => !(left == right);
 153
 154    #endregion
 155}