< Summary

Information
Class: FixedMathSharp.BoundingArea
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Geometry/Bounds/BoundingArea.cs
Line coverage
100%
Covered lines: 126
Uncovered lines: 0
Coverable lines: 126
Total lines: 471
Line coverage: 100%
Branch coverage
100%
Covered branches: 102
Total branches: 102
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%
get_Min()100%11100%
get_Max()100%11100%
get_MinX()100%22100%
get_MaxX()100%22100%
get_MinY()100%22100%
get_MaxY()100%22100%
get_MinZ()100%22100%
get_MaxZ()100%22100%
get_Width()100%11100%
get_Height()100%11100%
get_Depth()100%11100%
get_Center()100%11100%
Contains(...)100%1010100%
Contains(...)100%11100%
Contains(...)100%11100%
Contains(...)100%66100%
Contains(...)100%88100%
Intersects(...)100%11100%
Intersects(...)100%11100%
Intersects(...)100%11100%
Intersects(...)100%22100%
ProjectPoint(...)100%11100%
ClampPoint(...)100%11100%
Deconstruct(...)100%11100%
ContainsBoxLike(...)100%66100%
IntersectsBoxLike(...)100%1010100%
IntersectsSphere(...)100%11100%
ContainsPoint(...)100%1010100%
IsFlatAlongX(...)100%22100%
IsFlatAlongY(...)100%22100%
IsFlatAlongZ(...)100%22100%
OverlapsOnXY(...)100%66100%
OverlapsOnXZ(...)100%66100%
OverlapsOnYZ(...)100%66100%
OverlapsOnAllAxes(...)100%1010100%
Union(...)100%11100%
op_Equality(...)100%11100%
op_Inequality(...)100%11100%
Equals(...)100%22100%
Equals(...)100%22100%
GetHashCode()100%11100%

File(s)

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

#LineLine coverage
 1using MemoryPack;
 2using System;
 3using System.Runtime.CompilerServices;
 4using System.Text.Json.Serialization;
 5
 6namespace FixedMathSharp;
 7
 8/// <summary>
 9/// Represents a lightweight, axis-aligned bounding area with fixed-point precision, optimized for 2D or simplified 3D u
 10/// </summary>
 11/// <remarks>
 12/// The BoundingArea is designed for performance-critical scenarios where only a minimal bounding volume is required.
 13/// It offers fast containment and intersection checks with other bounds but lacks the full feature set of BoundingBox.
 14///
 15/// Use Cases:
 16/// - Efficient spatial queries in 2D or constrained 3D spaces (e.g., terrain maps or collision grids).
 17/// - Simplified bounding volume checks where rotation or complex shape fitting is not needed.
 18/// - Can be used as a broad-phase bounding volume to cull objects before more precise checks with BoundingBox or Boundi
 19/// </remarks>
 20
 21[Serializable]
 22[MemoryPackable]
 23public partial struct BoundingArea : IEquatable<BoundingArea>
 24{
 25    #region Fields
 26
 27    /// <summary>
 28    /// One of the corner points of the bounding area.
 29    /// </summary>
 30    [JsonInclude]
 31    [MemoryPackOrder(0)]
 32    public Vector3d Corner1;
 33
 34    /// <summary>
 35    /// The opposite corner point of the bounding area.
 36    /// </summary>
 37    [JsonInclude]
 38    [MemoryPackOrder(1)]
 39    public Vector3d Corner2;
 40
 41    #endregion
 42
 43    #region Constructors
 44
 45    /// <summary>
 46    /// Initializes a new instance of the BoundingArea struct with corner coordinates.
 47    /// </summary>
 48    public BoundingArea(Fixed64 c1x, Fixed64 c1y, Fixed64 c1z, Fixed64 c2x, Fixed64 c2y, Fixed64 c2z)
 149    {
 150        Corner1 = new Vector3d(c1x, c1y, c1z);
 151        Corner2 = new Vector3d(c2x, c2y, c2z);
 152    }
 53
 54    /// <summary>
 55    /// Initializes a new instance of the BoundingArea struct with two corner points.
 56    /// </summary>
 57    [JsonConstructor]
 58    public BoundingArea(Vector3d corner1, Vector3d corner2)
 8559    {
 8560        Corner1 = corner1;
 8561        Corner2 = corner2;
 8562    }
 63
 64    #endregion
 65
 66    #region Properties
 67
 68    // Min/Max properties for easy access to boundaries
 69
 70    /// <summary>
 71    /// The minimum corner of the bounding box.
 72    /// </summary>
 73    [JsonIgnore]
 74    [MemoryPackIgnore]
 75    public Vector3d Min
 76    {
 77        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 9278        get => new(MinX, MinY, MinZ);
 79    }
 80
 81    /// <summary>
 82    /// The maximum corner of the bounding box.
 83    /// </summary>
 84    [JsonIgnore]
 85    [MemoryPackIgnore]
 86    public Vector3d Max
 87    {
 88        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 9289        get => new(MaxX, MaxY, MaxZ);
 90    }
 91
 92    /// <summary>
 93    /// The minimum X coordinate of the bounding area.
 94    /// </summary>
 95    [JsonIgnore]
 96    [MemoryPackIgnore]
 97    public Fixed64 MinX
 98    {
 99        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 107100        get => Corner1.x < Corner2.x ? Corner1.x : Corner2.x;
 101    }
 102
 103    /// <summary>
 104    /// Gets the greater X-coordinate value of the two corners that define the bounding area.
 105    /// </summary>
 106    [JsonIgnore]
 107    [MemoryPackIgnore]
 108    public Fixed64 MaxX
 109    {
 110        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 105111        get => Corner1.x > Corner2.x ? Corner1.x : Corner2.x;
 112    }
 113
 114    /// <summary>
 115    /// Gets the minimum Y-coordinate value of the bounding area defined by Corner1 and Corner2.
 116    /// </summary>
 117    [JsonIgnore]
 118    [MemoryPackIgnore]
 119    public Fixed64 MinY
 120    {
 121        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 102122        get => Corner1.y < Corner2.y ? Corner1.y : Corner2.y;
 123    }
 124
 125    /// <summary>
 126    /// Gets the maximum Y-coordinate value of the bounding area defined by the two corners.
 127    /// </summary>
 128    [JsonIgnore]
 129    [MemoryPackIgnore]
 130    public Fixed64 MaxY
 131    {
 132        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 103133        get => Corner1.y > Corner2.y ? Corner1.y : Corner2.y;
 134    }
 135
 136    /// <summary>
 137    /// Gets the minimum Z coordinate value of the bounding volume.
 138    /// </summary>
 139    [JsonIgnore]
 140    [MemoryPackIgnore]
 141    public Fixed64 MinZ
 142    {
 143        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 102144        get => Corner1.z < Corner2.z ? Corner1.z : Corner2.z;
 145    }
 146
 147    /// <summary>
 148    /// Gets the maximum Z coordinate value between the two corners of the bounding box.
 149    /// </summary>
 150    [JsonIgnore]
 151    [MemoryPackIgnore]
 152    public Fixed64 MaxZ
 153    {
 154        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 102155        get => Corner1.z > Corner2.z ? Corner1.z : Corner2.z;
 156    }
 157
 158    /// <summary>
 159    /// Calculates the width (X-axis) of the bounding area.
 160    /// </summary>
 161    [JsonIgnore]
 162    [MemoryPackIgnore]
 163    public Fixed64 Width
 164    {
 165        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1166        get => MaxX - MinX;
 167    }
 168
 169    /// <summary>
 170    /// Calculates the height (Y-axis) of the bounding area.
 171    /// </summary>
 172    [JsonIgnore]
 173    [MemoryPackIgnore]
 174    public Fixed64 Height
 175    {
 176        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1177        get => MaxY - MinY;
 178    }
 179
 180    /// <summary>
 181    /// Calculates the depth (Z-axis) of the bounding area.
 182    /// </summary>
 183    [JsonIgnore]
 184    [MemoryPackIgnore]
 185    public Fixed64 Depth
 186    {
 187        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1188        get => MaxZ - MinZ;
 189    }
 190
 191    /// <summary>
 192    /// The center point of the bounding area.
 193    /// </summary>
 194    [JsonIgnore]
 195    [MemoryPackIgnore]
 196    public Vector3d Center
 197    {
 198        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1199        get => (Min + Max) * Fixed64.Half;
 200    }
 201
 202    #endregion
 203
 204    #region Methods (Instance)
 205
 206    /// <summary>
 207    /// Determines if a point is inside the bounding area (including boundaries).
 208    /// </summary>
 209    public bool Contains(Vector3d point)
 13210    {
 211        // Check if the point is within the bounds of the area (including boundaries)
 13212        return point.x >= MinX && point.x <= MaxX
 13213            && point.y >= MinY && point.y <= MaxY
 13214            && point.z >= MinZ && point.z <= MaxZ;
 13215    }
 216
 217    /// <summary>
 218    /// Tests another bounding area against this bounding area.
 219    /// </summary>
 220    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 4221    public ContainmentType Contains(BoundingArea area) => ContainsBoxLike(area.Min, area.Max);
 222
 223    /// <summary>
 224    /// Tests a bounding box against this bounding area.
 225    /// </summary>
 226    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1227    public ContainmentType Contains(BoundingBox box) => ContainsBoxLike(box.Min, box.Max);
 228
 229    /// <summary>
 230    /// Tests a bounding sphere against this bounding area.
 231    /// </summary>
 232    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 233    public ContainmentType Contains(BoundingSphere sphere)
 3234    {
 3235        if (Contains(sphere.Min) && Contains(sphere.Max))
 1236            return ContainmentType.Contains;
 237
 2238        return Intersects(sphere) ? ContainmentType.Intersects : ContainmentType.Disjoint;
 3239    }
 240
 241    /// <summary>
 242    /// Tests a bounding frustum against this bounding area.
 243    /// </summary>
 244    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 245    public ContainmentType Contains(BoundingFrustum frustum)
 4246    {
 4247        if (frustum == null)
 1248            throw new ArgumentNullException(nameof(frustum));
 249
 3250        if (Contains(frustum.Min) && Contains(frustum.Max))
 1251            return ContainmentType.Contains;
 252
 2253        return Intersects(frustum) ? ContainmentType.Intersects : ContainmentType.Disjoint;
 3254    }
 255
 256    /// <summary>
 257    /// Checks whether another bounding area intersects this bounding area.
 258    /// </summary>
 259    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 19260    public bool Intersects(BoundingArea area) => IntersectsBoxLike(area.Min, area.Max);
 261
 262    /// <summary>
 263    /// Checks whether a bounding box intersects this bounding area.
 264    /// </summary>
 265    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1266    public bool Intersects(BoundingBox box) => IntersectsBoxLike(box.Min, box.Max);
 267
 268    /// <summary>
 269    /// Checks whether a bounding sphere intersects this bounding area.
 270    /// </summary>
 271    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 3272    public bool Intersects(BoundingSphere sphere) => IntersectsSphere(sphere);
 273
 274    /// <summary>
 275    /// Checks whether a bounding frustum intersects this bounding area.
 276    /// </summary>
 277    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 278    public bool Intersects(BoundingFrustum frustum)
 5279    {
 5280        if (frustum == null)
 1281            throw new ArgumentNullException(nameof(frustum));
 282
 4283        return frustum.Intersects(this);
 4284    }
 285
 286    /// <summary>
 287    /// Projects a point into the bounding area by clamping it to the area extents.
 288    /// </summary>
 289    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 290    public Vector3d ProjectPoint(Vector3d point)
 1291    {
 1292        return ClampPoint(point);
 1293    }
 294
 295    /// <summary>
 296    /// Clamps a point to this bounding area, returning the point unchanged when it is already inside.
 297    /// </summary>
 298    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 299    public Vector3d ClampPoint(Vector3d point)
 5300    {
 5301        Vector3d min = Min;
 5302        Vector3d max = Max;
 303
 5304        return new Vector3d(
 5305            FixedMath.Clamp(point.x, min.x, max.x),
 5306            FixedMath.Clamp(point.y, min.y, max.y),
 5307            FixedMath.Clamp(point.z, min.z, max.z));
 5308    }
 309
 310    /// <summary>
 311    /// Deconstructs the bounding area into its stored corner points.
 312    /// </summary>
 313    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 314    public void Deconstruct(out Vector3d corner1, out Vector3d corner2)
 1315    {
 1316        corner1 = Corner1;
 1317        corner2 = Corner2;
 1318    }
 319
 320    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 321    private ContainmentType ContainsBoxLike(Vector3d otherMin, Vector3d otherMax)
 5322    {
 5323        Vector3d min = Min;
 5324        Vector3d max = Max;
 325
 5326        if (ContainsPoint(otherMin, min, max) && ContainsPoint(otherMax, min, max))
 3327            return ContainmentType.Contains;
 328
 2329        return IntersectsBoxLike(otherMin, otherMax)
 2330            ? ContainmentType.Intersects
 2331            : ContainmentType.Disjoint;
 5332    }
 333
 334    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 335    private bool IntersectsBoxLike(Vector3d otherMin, Vector3d otherMax)
 22336    {
 22337        Vector3d min = Min;
 22338        Vector3d max = Max;
 339
 22340        if (ContainsPoint(otherMin, min, max) && ContainsPoint(otherMax, min, max))
 1341            return true;
 342
 21343        if (IsFlatAlongZ(min, max, otherMin, otherMax))
 5344            return OverlapsOnXY(min, max, otherMin, otherMax);
 345
 16346        if (IsFlatAlongY(min, max, otherMin, otherMax))
 5347            return OverlapsOnXZ(min, max, otherMin, otherMax);
 348
 11349        if (IsFlatAlongX(min, max, otherMin, otherMax))
 5350            return OverlapsOnYZ(min, max, otherMin, otherMax);
 351
 6352        return OverlapsOnAllAxes(min, max, otherMin, otherMax);
 22353    }
 354
 355    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 356    private bool IntersectsSphere(BoundingSphere sphere)
 3357    {
 3358        return Vector3d.SqrDistance(sphere.Center, ClampPoint(sphere.Center)) <= sphere.SqrRadius;
 3359    }
 360
 361    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 362    private static bool ContainsPoint(Vector3d point, Vector3d min, Vector3d max)
 38363    {
 38364        return point.x >= min.x && point.x <= max.x
 38365            && point.y >= min.y && point.y <= max.y
 38366            && point.z >= min.z && point.z <= max.z;
 38367    }
 368
 369    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 370    private static bool IsFlatAlongX(Vector3d min, Vector3d max, Vector3d otherMin, Vector3d otherMax)
 11371        => min.x == max.x && otherMin.x == otherMax.x;
 372
 373    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 374    private static bool IsFlatAlongY(Vector3d min, Vector3d max, Vector3d otherMin, Vector3d otherMax)
 16375        => min.y == max.y && otherMin.y == otherMax.y;
 376
 377    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 378    private static bool IsFlatAlongZ(Vector3d min, Vector3d max, Vector3d otherMin, Vector3d otherMax)
 21379        => min.z == max.z && otherMin.z == otherMax.z;
 380
 381    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 382    private static bool OverlapsOnXY(Vector3d min, Vector3d max, Vector3d otherMin, Vector3d otherMax)
 5383    {
 5384        return !(max.x < otherMin.x || min.x > otherMax.x ||
 5385                 max.y < otherMin.y || min.y > otherMax.y);
 5386    }
 387
 388    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 389    private static bool OverlapsOnXZ(Vector3d min, Vector3d max, Vector3d otherMin, Vector3d otherMax)
 5390    {
 5391        return !(max.x < otherMin.x || min.x > otherMax.x ||
 5392                 max.z < otherMin.z || min.z > otherMax.z);
 5393    }
 394
 395    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 396    private static bool OverlapsOnYZ(Vector3d min, Vector3d max, Vector3d otherMin, Vector3d otherMax)
 5397    {
 5398        return !(max.y < otherMin.y || min.y > otherMax.y ||
 5399                 max.z < otherMin.z || min.z > otherMax.z);
 5400    }
 401
 402    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 403    private static bool OverlapsOnAllAxes(Vector3d min, Vector3d max, Vector3d otherMin, Vector3d otherMax)
 6404    {
 6405        return !(max.x < otherMin.x || min.x > otherMax.x ||
 6406                 max.y < otherMin.y || min.y > otherMax.y ||
 6407                 max.z < otherMin.z || min.z > otherMax.z);
 6408    }
 409
 410    #endregion
 411
 412    #region Static Ops
 413
 414    /// <summary>
 415    /// Creates a new bounding area that encloses both specified bounding areas.
 416    /// </summary>
 417    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 418    public static BoundingArea Union(BoundingArea a, BoundingArea b)
 1419    {
 1420        return new BoundingArea(Vector3d.Min(a.Min, b.Min), Vector3d.Max(a.Max, b.Max));
 1421    }
 422
 423    #endregion
 424
 425    #region Operators
 426
 427    /// <summary>
 428    /// Determines whether two BoundingArea instances are equal.
 429    /// </summary>
 430    /// <param name="left">The first BoundingArea to compare.</param>
 431    /// <param name="right">The second BoundingArea to compare.</param>
 432    /// <returns>true if the specified BoundingArea instances are equal; otherwise, false.</returns>
 433    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2434    public static bool operator ==(BoundingArea left, BoundingArea right) => left.Equals(right);
 435
 436    /// <summary>
 437    /// Determines whether two BoundingArea instances are not equal.
 438    /// </summary>
 439    /// <param name="left">The first BoundingArea to compare.</param>
 440    /// <param name="right">The second BoundingArea to compare.</param>
 441    /// <returns>true if the specified BoundingArea instances are not equal; otherwise, false.</returns>
 442    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1443    public static bool operator !=(BoundingArea left, BoundingArea right) => !left.Equals(right);
 444
 445    #endregion
 446
 447    #region Equality and HashCode Overrides
 448
 449    /// <inheritdoc/>
 450    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 2451    public override bool Equals(object? obj) => obj is BoundingArea other && Equals(other);
 452
 453    /// <inheritdoc/>
 454    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 6455    public bool Equals(BoundingArea other) => Corner1.Equals(other.Corner1) && Corner2.Equals(other.Corner2);
 456
 457    /// <inheritdoc/>
 458    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 459    public override int GetHashCode()
 2460    {
 461        unchecked
 2462        {
 2463            int hash = 17;
 2464            hash = hash * 23 + Corner1.GetHashCode();
 2465            hash = hash * 23 + Corner2.GetHashCode();
 2466            return hash;
 467        }
 2468    }
 469
 470    #endregion
 471}

Methods/Properties

.ctor(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
.ctor(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
get_Min()
get_Max()
get_MinX()
get_MaxX()
get_MinY()
get_MaxY()
get_MinZ()
get_MaxZ()
get_Width()
get_Height()
get_Depth()
get_Center()
Contains(FixedMathSharp.Vector3d)
Contains(FixedMathSharp.BoundingArea)
Contains(FixedMathSharp.BoundingBox)
Contains(FixedMathSharp.BoundingSphere)
Contains(FixedMathSharp.BoundingFrustum)
Intersects(FixedMathSharp.BoundingArea)
Intersects(FixedMathSharp.BoundingBox)
Intersects(FixedMathSharp.BoundingSphere)
Intersects(FixedMathSharp.BoundingFrustum)
ProjectPoint(FixedMathSharp.Vector3d)
ClampPoint(FixedMathSharp.Vector3d)
Deconstruct(FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&)
ContainsBoxLike(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
IntersectsBoxLike(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
IntersectsSphere(FixedMathSharp.BoundingSphere)
ContainsPoint(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
IsFlatAlongX(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
IsFlatAlongY(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
IsFlatAlongZ(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
OverlapsOnXY(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
OverlapsOnXZ(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
OverlapsOnYZ(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
OverlapsOnAllAxes(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
Union(FixedMathSharp.BoundingArea,FixedMathSharp.BoundingArea)
op_Equality(FixedMathSharp.BoundingArea,FixedMathSharp.BoundingArea)
op_Inequality(FixedMathSharp.BoundingArea,FixedMathSharp.BoundingArea)
Equals(System.Object)
Equals(FixedMathSharp.BoundingArea)
GetHashCode()