< Summary

Line coverage
100%
Covered lines: 61
Uncovered lines: 0
Coverable lines: 61
Total lines: 322
Line coverage: 100%
Branch coverage
100%
Covered branches: 26
Total branches: 26
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Bounds/FixedBoundCircle.BoundingCircleState.cs

#LineLine coverage
 1//=======================================================================
 2// FixedBoundCircle.BoundingCircleState.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 System;
 9using System.Runtime.CompilerServices;
 10using System.Text.Json.Serialization;
 11using MemoryPack;
 12
 13namespace FixedMathSharp.Geometry;
 14
 15/// <content>BoundingCircleState declaration for FixedBoundCircle.</content>
 16public partial struct FixedBoundCircle
 17{
 18    /// <summary>
 19    /// Represents the normalized serializable state of a two-dimensional circular bound.
 20    /// </summary>
 21    [Serializable]
 22    [MemoryPackable]
 23    public readonly partial struct BoundingCircleState
 24    {
 25        /// <inheritdoc cref="FixedBoundCircle.Center"/>
 26        [JsonInclude]
 27        [MemoryPackInclude]
 28        public readonly Vector2d Center;
 29
 30        /// <inheritdoc cref="FixedBoundCircle.Radius"/>
 31        [JsonInclude]
 32        [MemoryPackInclude]
 33        public readonly Fixed64 Radius;
 34
 35        /// <summary>
 36        /// Initializes a normalized state from center and radius.
 37        /// </summary>
 38        [JsonConstructor]
 39        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 40        public BoundingCircleState(Vector2d center, Fixed64 radius)
 41        {
 342            Center = center;
 343            Radius = NormalizeRadius(radius);
 344        }
 45    }
 46}

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Bounds/FixedBoundCircle.cs

#LineLine coverage
 1//=======================================================================
 2// FixedBoundCircle.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 System;
 9using System.Runtime.CompilerServices;
 10using System.Text.Json.Serialization;
 11using MemoryPack;
 12
 13namespace FixedMathSharp.Geometry;
 14
 15/// <summary>
 16/// Represents a normalized two-dimensional circular bound.
 17/// </summary>
 18/// <remarks>
 19/// Radius inputs are normalized by absolute value so a public circle cannot
 20/// retain a negative radius through construction, assignment, or state load.
 21/// </remarks>
 22[Serializable]
 23[MemoryPackable]
 24public partial struct FixedBoundCircle : IEquatable<FixedBoundCircle>
 25{
 26
 27    #region Fields
 28
 29    private Fixed64 _radius;
 30
 31    #endregion
 32
 33    #region Constructors
 34
 35    /// <summary>
 36    /// Initializes a new instance from a center point and radius.
 37    /// </summary>
 38    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 39    public FixedBoundCircle(Vector2d center, Fixed64 radius)
 40    {
 10341        Center = center;
 10342        _radius = NormalizeRadius(radius);
 10343    }
 44
 45    /// <summary>
 46    /// Initializes a new instance from serialized or caller-provided state.
 47    /// </summary>
 48    [JsonConstructor]
 49    public FixedBoundCircle(BoundingCircleState state)
 50    {
 251        Center = state.Center;
 252        _radius = state.Radius;
 253    }
 54
 55    #endregion
 56
 57    #region Properties
 58
 59    /// <summary>
 60    /// The center point of the circle.
 61    /// </summary>
 62    [JsonIgnore]
 63    [MemoryPackIgnore]
 64    public Vector2d Center { get; set; }
 65
 66    /// <summary>
 67    /// The non-negative radius of the circle. Assigned values are normalized by absolute value.
 68    /// </summary>
 69    [JsonIgnore]
 70    [MemoryPackIgnore]
 71    public Fixed64 Radius
 72    {
 73        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 21974        get => _radius;
 75
 76        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 177        set => _radius = NormalizeRadius(value);
 78    }
 79
 80    /// <summary>
 81    /// The normalized axis-aligned representable-domain intersection that
 82    /// contains every representable point of the circle.
 83    /// </summary>
 84    [JsonIgnore]
 85    [MemoryPackIgnore]
 86    public FixedBoundArea Bounds
 87    {
 88        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 489        get => FixedBoundArea.FromCenterAndScopeClippedToDomain(Center, new Vector2d(Radius, Radius));
 90    }
 91
 92    /// <summary>
 93    /// Gets the current normalized state of the circle.
 94    /// </summary>
 95    [JsonInclude]
 96    [MemoryPackInclude]
 197    public BoundingCircleState State => new(Center, Radius);
 98
 99    #endregion
 100
 101    #region Spatial Queries
 102
 103    /// <summary>
 104    /// Determines whether the point is inside this circle, including the boundary.
 105    /// </summary>
 106    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 107    public bool Contains(Vector2d point)
 108    {
 10109        return WideGeometry.CompareDistanceToRadiusSum(Center, point, Radius, Fixed64.Zero) <= 0;
 110    }
 111
 112    /// <summary>
 113    /// Returns whether the point lies strictly inside this circle.
 114    /// </summary>
 115    /// <remarks>
 116    /// Boundary points and every point tested against a zero-radius circle
 117    /// return <see langword="false"/>.
 118    /// </remarks>
 119    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 120    public bool ContainsStrict(Vector2d point) =>
 3121        Radius > Fixed64.Zero
 3122        && WideGeometry.CompareDistanceToRadiusSum(Center, point, Radius, Fixed64.Zero) < 0;
 123
 124    /// <summary>
 125    /// Classifies another circle against this circle using boundary-inclusive overlap.
 126    /// </summary>
 127    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 128    public FixedEnclosureType Contains(FixedBoundCircle circle)
 129    {
 14130        if (WideGeometry.CompareDistanceToRadiusSum(Center, circle.Center, Radius, circle.Radius) > 0)
 5131            return FixedEnclosureType.Disjoint;
 132
 9133        Fixed64 radiusDifference = Radius - circle.Radius;
 9134        if (radiusDifference >= Fixed64.Zero
 9135            && WideGeometry.CompareDistanceToRadiusSum(
 9136                Center,
 9137                circle.Center,
 9138                radiusDifference,
 9139                Fixed64.Zero) <= 0)
 2140            return FixedEnclosureType.Contains;
 141
 7142        return FixedEnclosureType.Intersects;
 143    }
 144
 145    /// <summary>
 146    /// Determines whether another circle intersects this circle, including boundary-only contact.
 147    /// </summary>
 148    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 5149    public bool Intersects(FixedBoundCircle circle) => Contains(circle) != FixedEnclosureType.Disjoint;
 150
 151    /// <summary>
 152    /// Determines whether an area intersects this circle, including boundary-only contact.
 153    /// </summary>
 154    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 155    public bool Intersects(FixedBoundArea area)
 156    {
 19157        return WideGeometry.CompareDistanceToRadiusSum(
 19158            Center,
 19159            area.ClampPoint(Center),
 19160            Radius,
 19161            Fixed64.Zero) <= 0;
 162    }
 163
 164    /// <summary>
 165    /// Determines whether another circle overlaps this circle with positive area.
 166    /// </summary>
 167    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 168    public bool IntersectsStrict(FixedBoundCircle circle)
 169    {
 4170        return Radius > Fixed64.Zero
 4171            && circle.Radius > Fixed64.Zero
 4172            && WideGeometry.CompareDistanceToRadiusSum(Center, circle.Center, Radius, circle.Radius) < 0;
 173    }
 174
 175    /// <summary>
 176    /// Determines whether an area overlaps this circle with positive area.
 177    /// </summary>
 178    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 179    public bool IntersectsStrict(FixedBoundArea area)
 180    {
 7181        return Radius > Fixed64.Zero
 7182            && area.Min.X < area.Max.X
 7183            && area.Min.Y < area.Max.Y
 7184            && WideGeometry.CompareDistanceToRadiusSum(
 7185                Center,
 7186                area.ClampPoint(Center),
 7187                Radius,
 7188                Fixed64.Zero) < 0;
 189    }
 190
 191    /// <summary>
 192    /// Clamps a point to this circle, returning the point unchanged when it is already inside.
 193    /// </summary>
 194    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 195    public Vector2d ClampPoint(Vector2d point)
 196    {
 3197        return Contains(point) ? point : ProjectPoint(point);
 198    }
 199
 200    /// <summary>
 201    /// Projects a point onto the circle boundary. The center is returned when the direction is degenerate.
 202    /// </summary>
 203    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 204    public Vector2d ProjectPoint(Vector2d point)
 205    {
 3206        Vector2d direction = point - Center;
 3207        if (direction.EqualsZero())
 1208            return Center;
 209
 2210        return Center + direction.NormalizeInPlace() * Radius;
 211    }
 212
 213    #endregion
 214
 215    #region Deconstruction
 216
 217    /// <summary>
 218    /// Deconstructs the circle into center and normalized radius.
 219    /// </summary>
 220    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 221    public void Deconstruct(out Vector2d center, out Fixed64 radius)
 222    {
 1223        center = Center;
 1224        radius = Radius;
 1225    }
 226
 227    #endregion
 228
 229    #region Equality
 230
 231    /// <inheritdoc />
 232    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 233    public bool Equals(FixedBoundCircle other)
 234    {
 9235        return Center == other.Center && Radius == other.Radius;
 236    }
 237
 238    /// <inheritdoc />
 239    public override bool Equals(object? obj)
 240    {
 2241        return obj is FixedBoundCircle other && Equals(other);
 242    }
 243
 244    /// <inheritdoc />
 245    public override int GetHashCode()
 246    {
 247        unchecked
 248        {
 3249            int hash = 17;
 3250            hash = (hash * 31) + Center.StateHash;
 3251            hash = (hash * 31) + Radius.GetHashCode();
 3252            return hash;
 253        }
 254    }
 255
 256    /// <summary>
 257    /// Determines whether two circles have the same normalized state.
 258    /// </summary>
 259    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2260    public static bool operator ==(FixedBoundCircle left, FixedBoundCircle right) => left.Equals(right);
 261
 262    /// <summary>
 263    /// Determines whether two circles have different normalized state.
 264    /// </summary>
 265    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2266    public static bool operator !=(FixedBoundCircle left, FixedBoundCircle right) => !left.Equals(right);
 267
 268    #endregion
 269
 270    #region Helpers
 271
 272    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 107273    private static Fixed64 NormalizeRadius(Fixed64 radius) => FixedMath.Abs(radius);
 274
 275    #endregion
 276}