< Summary

Information
Class: Gravitas.Constraints.JointLimit3D
Assembly: Gravitas
File(s): /home/runner/work/Gravitas/Gravitas/src/Gravitas/Constraints/3D/JointLimit3D.cs
Line coverage
100%
Covered lines: 22
Uncovered lines: 0
Coverable lines: 22
Total lines: 88
Line coverage: 100%
Branch coverage
100%
Covered branches: 4
Total branches: 4
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
get_Unrestricted()100%11100%
Hinge(...)100%11100%
ConeTwist(...)100%11100%
Validate()100%44100%
ValidateNonNegative(...)100%11100%

File(s)

/home/runner/work/Gravitas/Gravitas/src/Gravitas/Constraints/3D/JointLimit3D.cs

#LineLine coverage
 1//=======================================================================
 2// JointLimit3D.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2026-present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using FixedMathSharp;
 9
 10namespace Gravitas.Constraints;
 11
 12/// <summary>
 13/// Optional deterministic angular limit payload for a 3D joint.
 14/// </summary>
 15public readonly struct JointLimit3D
 16{
 17    private JointLimit3D(
 18        JointLimitKind3D kind,
 19        Fixed64 maxHingeAngle,
 20        Fixed64 maxConeAngle,
 21        Fixed64 maxTwistAngle)
 22    {
 5523        Kind = kind;
 5524        MaxHingeAngle = maxHingeAngle;
 5525        MaxConeAngle = maxConeAngle;
 5526        MaxTwistAngle = maxTwistAngle;
 5527    }
 28
 29    /// <summary>
 30    /// Gets an unrestricted limit payload.
 31    /// </summary>
 27232    public static JointLimit3D Unrestricted => default;
 33
 34    /// <summary>
 35    /// Gets the active limit family.
 36    /// </summary>
 37    public JointLimitKind3D Kind { get; }
 38
 39    /// <summary>
 40    /// Gets the maximum absolute hinge angle in radians.
 41    /// </summary>
 42    public Fixed64 MaxHingeAngle { get; }
 43
 44    /// <summary>
 45    /// Gets the maximum cone swing angle in radians.
 46    /// </summary>
 47    public Fixed64 MaxConeAngle { get; }
 48
 49    /// <summary>
 50    /// Gets the maximum absolute twist angle in radians.
 51    /// </summary>
 52    public Fixed64 MaxTwistAngle { get; }
 53
 54    /// <summary>
 55    /// Creates a hinge limit around the local X axis.
 56    /// </summary>
 57    public static JointLimit3D Hinge(Fixed64 maxAngle)
 58    {
 3859        ValidateNonNegative(maxAngle, nameof(maxAngle));
 3860        return new JointLimit3D(JointLimitKind3D.Hinge, maxAngle, Fixed64.Zero, Fixed64.Zero);
 61    }
 62
 63    /// <summary>
 64    /// Creates a cone-twist limit around the local Z axis.
 65    /// </summary>
 66    public static JointLimit3D ConeTwist(Fixed64 maxConeAngle, Fixed64 maxTwistAngle)
 67    {
 1768        ValidateNonNegative(maxConeAngle, nameof(maxConeAngle));
 1769        ValidateNonNegative(maxTwistAngle, nameof(maxTwistAngle));
 1770        return new JointLimit3D(JointLimitKind3D.ConeTwist, Fixed64.Zero, maxConeAngle, maxTwistAngle);
 71    }
 72
 73    internal void Validate()
 74    {
 37375        SwiftThrowHelper.ThrowIfArgument(
 37376            Kind != JointLimitKind3D.Unrestricted
 37377                && Kind != JointLimitKind3D.Hinge
 37378                && Kind != JointLimitKind3D.ConeTwist,
 37379            nameof(Kind),
 37380            "Unsupported joint limit kind.");
 37381        ValidateNonNegative(MaxHingeAngle, nameof(MaxHingeAngle));
 37382        ValidateNonNegative(MaxConeAngle, nameof(MaxConeAngle));
 37383        ValidateNonNegative(MaxTwistAngle, nameof(MaxTwistAngle));
 37384    }
 85
 86    private static void ValidateNonNegative(Fixed64 value, string name) =>
 119187        SwiftThrowHelper.ThrowIfArgument(value < Fixed64.Zero, name, "Joint limit angles cannot be negative.");
 88}