1- using System . Runtime . CompilerServices ;
1+ using System . Diagnostics ;
2+ using System . Runtime . CompilerServices ;
3+ using System . Runtime . InteropServices ;
4+ using Hypercube . Mathematics . Extensions ;
25using Hypercube . Mathematics . Vectors ;
6+ using JetBrains . Annotations ;
37
48namespace 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