Skip to content

Commit 829973b

Browse files
ref: circle
1 parent 30602bc commit 829973b

1 file changed

Lines changed: 167 additions & 7 deletions

File tree

Lines changed: 167 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,178 @@
1-
using System.Runtime.CompilerServices;
1+
using System.Diagnostics;
2+
using System.Runtime.CompilerServices;
3+
using System.Runtime.InteropServices;
4+
using Hypercube.Mathematics.Extensions;
25
using Hypercube.Mathematics.Vectors;
6+
using JetBrains.Annotations;
37

48
namespace Hypercube.Mathematics.Shapes;
59

6-
public readonly struct Circle(Vector2 position, float radius)
10+
[PublicAPI, Serializable, StructLayout(LayoutKind.Sequential)]
11+
[DebuggerDisplay("{ToString()}")]
12+
public readonly struct Circle : IEquatable<Circle>
713
{
8-
public readonly Vector2 Position = position;
9-
public readonly float Radius = radius;
14+
public static readonly Circle NaN = new(Vector2.NaN, float.NaN);
15+
public static readonly Circle Zero = new(Vector2.Zero, 0);
16+
public static readonly Circle Unit = new(Vector2.Zero, 1);
1017

11-
public float Area => Radius * Radius * HyperMath.PIf;
18+
public readonly Vector2 Position;
19+
public readonly float Radius;
20+
21+
public float Diameter
22+
{
23+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
24+
get => 2 * Radius;
25+
}
26+
27+
public float Area
28+
{
29+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
30+
get => Radius * Radius * HyperMath.PIf;
31+
}
32+
33+
public float Circumference
34+
{
35+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
36+
get => 2 * HyperMath.PIf * Radius;
37+
}
38+
39+
public Rect2 BoundingBox
40+
{
41+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
42+
get => new(
43+
Position.X - Radius,
44+
Position.Y + Radius,
45+
Position.X + Radius,
46+
Position.Y - Radius);
47+
}
48+
49+
public bool IsValid
50+
{
51+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
52+
get => !float.IsNaN(Position.X) &&
53+
!float.IsNaN(Position.Y) &&
54+
!float.IsNaN(Radius);
55+
}
56+
57+
public Circle(Vector2 position, float radius)
58+
{
59+
ArgumentOutOfRangeException.ThrowIfNegative(radius);
60+
61+
Position = position;
62+
Radius = radius;
63+
}
64+
65+
public Circle(Circle circle)
66+
{
67+
ArgumentOutOfRangeException.ThrowIfNegative(circle.Radius);
68+
69+
Position = circle.Position;
70+
Radius = circle.Radius;
71+
}
72+
73+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
74+
public void Deconstruct(out Vector2 position, out float radius)
75+
{
76+
position = Position;
77+
radius = Radius;
78+
}
79+
80+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
81+
public Circle WithPosition(Vector2 position)
82+
{
83+
return new Circle(position, Radius);
84+
}
85+
86+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
87+
public Circle WithRadius(float radius)
88+
{
89+
return new Circle(Position, radius);
90+
}
91+
92+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
93+
public Circle Translate(Vector2 direction)
94+
{
95+
return WithPosition(Position + direction);
96+
}
97+
98+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
99+
public Circle Scale(float factor)
100+
{
101+
return WithRadius(Radius * factor);
102+
}
12103

13104
[MethodImpl(MethodImplOptions.AggressiveInlining)]
14-
public static Circle operator +(Circle a, Vector2 b)
105+
public bool Contains(Vector2 point)
106+
{
107+
return (point - Position).LengthSquared <= Radius * Radius;
108+
}
109+
110+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
111+
public bool Contains(Circle other)
112+
{
113+
return (other.Position - Position).LengthSquared <= (Radius - other.Radius) * (Radius - other.Radius);
114+
}
115+
116+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
117+
public bool Intersects(Circle other)
118+
{
119+
var rad = Radius + other.Radius;
120+
return (other.Position - Position).LengthSquared <= rad * rad;
121+
}
122+
123+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
124+
public Vector2 NearestPoint(Vector2 point)
125+
{
126+
var dir = point - Position;
127+
var lenSquared = dir.LengthSquared;
128+
if (lenSquared <= Radius * Radius)
129+
return point;
130+
131+
var len = 1 / float.ReciprocalSqrtEstimate(lenSquared);
132+
return Position + dir / len * Radius;
133+
}
134+
135+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
136+
public override string ToString()
137+
{
138+
return $"[({Position}), ({Radius})]";
139+
}
140+
141+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
142+
public bool Equals(Circle other)
143+
{
144+
return Position.Equals(other.Position) &&
145+
Radius.AboutEquals(other.Radius);
146+
}
147+
148+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
149+
public bool Equals(Circle other, float tolerance)
150+
{
151+
return Position.Equals(other.Position, tolerance) &&
152+
Radius.AboutEquals(other.Radius, tolerance);
153+
}
154+
155+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
156+
public override bool Equals(object? obj)
157+
{
158+
return obj is Circle other && Equals(other);
159+
}
160+
161+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
162+
public override int GetHashCode()
163+
{
164+
return HashCode.Combine(Position, Radius);
165+
}
166+
167+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
168+
public static bool operator ==(Circle a, Circle b)
169+
{
170+
return a.Equals(b);
171+
}
172+
173+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
174+
public static bool operator !=(Circle a, Circle b)
15175
{
16-
return new Circle(a.Position + b, a.Radius);
176+
return !a.Equals(b);
17177
}
18178
}

0 commit comments

Comments
 (0)