< Summary

Information
Class: FixedMathSharp.FixedCurve
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Numerics/Curves/FixedCurve.cs
Line coverage
100%
Covered lines: 40
Uncovered lines: 0
Coverable lines: 40
Total lines: 161
Line coverage: 100%
Branch coverage
100%
Covered branches: 30
Total branches: 30
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor(...)100%11100%
.ctor(...)100%44100%
Evaluate(...)100%1414100%
Equals(...)100%88100%
Equals(...)100%22100%
GetHashCode()100%22100%
op_Equality(...)100%11100%
op_Inequality(...)100%11100%

File(s)

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

#LineLine coverage
 1//=======================================================================
 2// FixedCurve.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using MemoryPack;
 9using System;
 10using System.Text.Json.Serialization;
 11
 12namespace FixedMathSharp;
 13
 14/// <summary>
 15/// A deterministic fixed-point curve that interpolates values between keyframes.
 16/// Used for animations, physics calculations, and procedural data.
 17/// </summary>
 18[Serializable]
 19[MemoryPackable]
 20public partial struct FixedCurve : IEquatable<FixedCurve>
 21{
 122    private static readonly Comparison<FixedCurveKey> CompareKeyframesByTime = (left, right) => left.Time.CompareTo(righ
 23
 24    #region Constructors
 25
 26    /// <summary>
 27    /// Initializes a new instance of the <see cref="FixedCurve"/> with a default linear interpolation mode.
 28    /// </summary>
 29    /// <param name="keyframes">The keyframes defining the curve.</param>
 30    public FixedCurve(params FixedCurveKey[] keyframes)
 1031        : this(FixedCurveMode.Linear, keyframes) { }
 32
 33    /// <summary>
 34    /// Initializes a new instance of the <see cref="FixedCurve"/> with a specified interpolation mode.
 35    /// </summary>
 36    /// <param name="mode">The interpolation method to use.</param>
 37    /// <param name="keyframes">The keyframes defining the curve.</param>
 38    [JsonConstructor]
 39    [MemoryPackConstructor]
 40    public FixedCurve(FixedCurveMode mode, params FixedCurveKey[] keyframes)
 41    {
 2242        if (keyframes is null)
 143            Keyframes = Array.Empty<FixedCurveKey>();
 44        else
 45        {
 2146            if (keyframes.Length > 1)
 1947                Array.Sort(keyframes, CompareKeyframesByTime);
 48
 2149            Keyframes = keyframes;
 50        }
 51
 2252        Mode = mode;
 2253    }
 54
 55    #endregion
 56
 57    #region Properties
 58
 59    /// <summary>
 60    /// Gets the mode used for the fixed curve calculation.
 61    /// </summary>
 62    [JsonInclude]
 63    [MemoryPackOrder(0)]
 64    [MemoryPackAllowSerialize]
 65    public FixedCurveMode Mode { get; private set; }
 66
 67    /// <summary>
 68    /// Gets the collection of keyframes that define the curve.
 69    /// </summary>
 70    [JsonInclude]
 71    [MemoryPackOrder(1)]
 72    public FixedCurveKey[] Keyframes { get; private set; }
 73
 74    #endregion
 75
 76    #region Methods
 77
 78    /// <summary>
 79    /// Evaluates the curve at a given time using the specified interpolation mode.
 80    /// </summary>
 81    /// <param name="time">The time at which to evaluate the curve.</param>
 82    /// <returns>The interpolated value at the given time.</returns>
 83    public Fixed64 Evaluate(Fixed64 time)
 84    {
 2485        if (Keyframes.Length == 0) return Fixed64.One;
 86
 87        // Clamp input within the keyframe range
 2988        if (time <= Keyframes[0].Time) return Keyframes[0].Value;
 2289        if (time >= Keyframes[^1].Time) return Keyframes[^1].Value;
 90
 91        // Find the surrounding keyframes. The constructor sorts keyframes, and the range checks above guarantee
 92        // that an interior time belongs to one of these segments.
 893        int segmentIndex = Keyframes.Length - 2;
 2494        for (int i = 0; i < Keyframes.Length - 1; i++)
 95        {
 1296            if (time < Keyframes[i + 1].Time)
 97            {
 898                segmentIndex = i;
 899                break;
 100            }
 101        }
 102
 8103        FixedCurveKey current = Keyframes[segmentIndex];
 8104        FixedCurveKey next = Keyframes[segmentIndex + 1];
 8105        Fixed64 t = (time - current.Time) / (next.Time - current.Time);
 106
 8107        return Mode switch
 8108        {
 3109            FixedCurveMode.Step => current.Value,
 1110            FixedCurveMode.Smooth => FixedMath.SmoothStep(current.Value, next.Value, t),
 1111            FixedCurveMode.Cubic => FixedMath.CubicInterpolate(current.Value, next.Value, current.OutTangent, next.InTan
 3112            _ => FixedMath.Lerp(current.Value, next.Value, t),
 8113        };
 114    }
 115
 116    #endregion
 117
 118    #region Equality
 119
 120    /// <inheritdoc/>
 121    public bool Equals(FixedCurve other)
 122    {
 8123        if (Mode != other.Mode || Keyframes.Length != other.Keyframes.Length)
 1124            return false;
 125
 44126        for (int i = 0; i < Keyframes.Length; i++)
 127        {
 16128            if (Keyframes[i] != other.Keyframes[i])
 1129                return false;
 130        }
 131
 6132        return true;
 133    }
 134
 135    /// <inheritdoc/>
 3136    public override bool Equals(object? obj) => obj is FixedCurve other && Equals(other);
 137
 138    /// <inheritdoc/>
 139    public override int GetHashCode()
 140    {
 141        unchecked
 142        {
 2143            int hash = (int)Mode;
 12144            foreach (var key in Keyframes)
 4145                hash = (hash * 31) ^ key.GetHashCode();
 2146            return hash;
 147        }
 148    }
 149
 150    /// <summary>
 151    /// Determines whether two FixedCurve instances are equal.
 152    /// </summary>
 3153    public static bool operator ==(FixedCurve left, FixedCurve right) => left.Equals(right);
 154
 155    /// <summary>
 156    /// Determines whether two FixedCurve instances are not equal.
 157    /// </summary>
 2158    public static bool operator !=(FixedCurve left, FixedCurve right) => !(left == right);
 159
 160    #endregion
 161}