< Summary

Information
Class: Gravitas.CollisionHandling.ManifoldContact2D
Assembly: Gravitas
File(s): /home/runner/work/Gravitas/Gravitas/src/Gravitas/CollisionHandling/Contacts/2D/ManifoldContact2D.cs
Line coverage
100%
Covered lines: 46
Uncovered lines: 0
Coverable lines: 46
Total lines: 185
Line coverage: 100%
Branch coverage
100%
Covered branches: 8
Total branches: 8
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%
.ctor(...)100%11100%
.ctor(...)100%66100%
get_PointA()100%11100%
get_PointB()100%11100%
TryGetPointA(...)100%11100%
TryGetPointB(...)100%11100%
GetRequiredWorldPoint(...)100%22100%

File(s)

/home/runner/work/Gravitas/Gravitas/src/Gravitas/CollisionHandling/Contacts/2D/ManifoldContact2D.cs

#LineLine coverage
 1//=======================================================================
 2// ManifoldContact2D.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;
 9using Gravitas.Materials;
 10using System;
 11using System.Runtime.CompilerServices;
 12
 13namespace Gravitas.CollisionHandling;
 14
 15/// <summary>
 16/// A deterministic pure 2D narrow-phase contact point for a collision manifold.
 17/// </summary>
 18public readonly struct ManifoldContact2D
 19{
 20    /// <summary>Creates a deterministic planar contact from world-space witness points.</summary>
 21    public ManifoldContact2D(
 22        ulong contactId,
 23        Vector2d pointA,
 24        Vector2d pointB,
 25        Fixed64 depth,
 26        Vector2d normal,
 27        bool hasMaterialOverride = false,
 28        PhysicsMaterial materialA = default,
 29        PhysicsMaterial materialB = default,
 30        bool depthIsClamped = false)
 2431        : this(
 2432            contactId,
 2433            ContactAnchor2D.FromWorldPoint(pointA),
 2434            ContactAnchor2D.FromWorldPoint(pointB),
 2435            depth,
 2436            normal,
 2437            hasMaterialOverride,
 2438            materialA,
 2439            materialB,
 2440            depthIsClamped)
 2441    { }
 42
 43    /// <summary>
 44    /// Creates a deterministic planar contact from authoritative relative
 45    /// anchors.
 46    /// </summary>
 47    public ManifoldContact2D(
 48        ulong contactId,
 49        ContactAnchor2D anchorA,
 50        ContactAnchor2D anchorB,
 51        Fixed64 depth,
 52        Vector2d normal,
 53        bool hasMaterialOverride = false,
 54        PhysicsMaterial materialA = default,
 55        PhysicsMaterial materialB = default,
 56        bool depthIsClamped = false)
 2657        : this(
 2658            contactId,
 2659            anchorA,
 2660            anchorB,
 2661            depth,
 2662            normal,
 2663            hasMaterialOverride,
 2664            materialA,
 2665            materialB,
 2666            depthIsClamped,
 2667            featureNamespaceA: 0,
 2668            featureNamespaceB: 0)
 2669    { }
 70
 71    internal ManifoldContact2D(
 72        ulong contactId,
 73        ContactAnchor2D anchorA,
 74        ContactAnchor2D anchorB,
 75        Fixed64 depth,
 76        Vector2d normal,
 77        bool hasMaterialOverride,
 78        PhysicsMaterial materialA,
 79        PhysicsMaterial materialB,
 80        bool depthIsClamped,
 81        int featureNamespaceA,
 82        int featureNamespaceB)
 83    {
 82484        ContactId = contactId;
 82485        AnchorA = anchorA;
 82486        AnchorB = anchorB;
 82487        FeatureNamespaceA = featureNamespaceA;
 82488        FeatureNamespaceB = featureNamespaceB;
 82489        Depth = depth.Abs();
 82490        DepthIsClamped = depthIsClamped;
 82491        Normal = normal.MagnitudeSquared > Fixed64.Epsilon
 82492            ? normal.Normalized
 82493            : Vector2d.Zero;
 82494        HasMaterialOverride = hasMaterialOverride;
 82495        MaterialA = hasMaterialOverride ? materialA : PhysicsMaterial.Default;
 82496        MaterialB = hasMaterialOverride ? materialB : PhysicsMaterial.Default;
 82497    }
 98
 99    /// <summary>
 100    /// Stable identity derived from the unordered pair of pose-invariant
 101    /// canonical local feature terms.
 102    /// </summary>
 103    public ulong ContactId { get; }
 104
 105    /// <summary>
 106    /// Authoritative canonical contact anchor on collider A.
 107    /// </summary>
 108    public ContactAnchor2D AnchorA { get; }
 109
 110    /// <summary>
 111    /// Authoritative canonical contact anchor on collider B.
 112    /// </summary>
 113    public ContactAnchor2D AnchorB { get; }
 114
 115    internal int FeatureNamespaceA { get; }
 116
 117    internal int FeatureNamespaceB { get; }
 118
 119    /// <summary>
 120    /// Gets the world-space X/Z-plane contact point on collider A.
 121    /// </summary>
 122    /// <exception cref="InvalidOperationException">
 123    /// The conceptual world point is outside the scalar range.
 124    /// </exception>
 54125    public Vector2d PointA => GetRequiredWorldPoint(AnchorA, nameof(PointA));
 126
 127    /// <summary>
 128    /// Gets the world-space X/Z-plane contact point on collider B.
 129    /// </summary>
 130    /// <exception cref="InvalidOperationException">
 131    /// The conceptual world point is outside the scalar range.
 132    /// </exception>
 50133    public Vector2d PointB => GetRequiredWorldPoint(AnchorB, nameof(PointB));
 134
 135    /// <summary>
 136    /// Attempts to materialize the world-space contact point on collider A.
 137    /// </summary>
 138    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 31139    public bool TryGetPointA(out Vector2d point) => AnchorA.TryGetWorldPoint(out point);
 140
 141    /// <summary>
 142    /// Attempts to materialize the world-space contact point on collider B.
 143    /// </summary>
 144    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 26145    public bool TryGetPointB(out Vector2d point) => AnchorB.TryGetWorldPoint(out point);
 146
 147    /// <summary>
 148    /// Penetration depth along <see cref="Normal"/>.
 149    /// </summary>
 150    public Fixed64 Depth { get; }
 151
 152    /// <summary>
 153    /// Gets whether the conceptual penetration depth exceeded the scalar range.
 154    /// </summary>
 155    public bool DepthIsClamped { get; }
 156
 157    /// <summary>
 158    /// Unit normal pointing from collider A toward collider B.
 159    /// </summary>
 160    public Vector2d Normal { get; }
 161
 162    /// <summary>
 163    /// Gets whether this contact carries materials from private compound parts.
 164    /// </summary>
 165    public bool HasMaterialOverride { get; }
 166
 167    /// <summary>
 168    /// Material for collider A when <see cref="HasMaterialOverride"/> is true.
 169    /// </summary>
 170    public PhysicsMaterial MaterialA { get; }
 171
 172    /// <summary>
 173    /// Material for collider B when <see cref="HasMaterialOverride"/> is true.
 174    /// </summary>
 175    public PhysicsMaterial MaterialB { get; }
 176
 177    private static Vector2d GetRequiredWorldPoint(ContactAnchor2D anchor, string propertyName)
 178    {
 104179        if (anchor.TryGetWorldPoint(out Vector2d point))
 103180            return point;
 181
 1182        throw new InvalidOperationException(
 1183            $"{propertyName} is outside the representable coordinate range. Use the corresponding TryGet method.");
 184    }
 185}