@@ -191,8 +191,8 @@ impl Circle {
191
191
pub struct Arc {
192
192
/// The radius of the circle
193
193
pub radius : f32 ,
194
- /// The angle swept out by the arc.
195
- pub angle : f32 ,
194
+ /// Half the angle swept out by the arc.
195
+ pub half_angle : f32 ,
196
196
}
197
197
impl Primitive2d for Arc { }
198
198
@@ -201,22 +201,31 @@ impl Default for Arc {
201
201
fn default ( ) -> Self {
202
202
Self {
203
203
radius : 0.5 ,
204
- angle : 1.0 ,
204
+ half_angle : 0.5 ,
205
205
}
206
206
}
207
207
}
208
208
209
209
impl Arc {
210
210
/// Create a new [`Arc`] from a `radius`, and an `angle`
211
211
#[ inline( always) ]
212
- pub const fn new ( radius : f32 , angle : f32 ) -> Self {
213
- Self { radius, angle }
212
+ pub fn new ( radius : f32 , angle : f32 ) -> Self {
213
+ Self {
214
+ radius,
215
+ half_angle : angle / 2.0 ,
216
+ }
217
+ }
218
+
219
+ /// Get the angle of the arc
220
+ #[ inline( always) ]
221
+ pub fn angle ( & self ) -> f32 {
222
+ self . half_angle * 2.0
214
223
}
215
224
216
225
/// Get the length of the arc
217
226
#[ inline( always) ]
218
227
pub fn length ( & self ) -> f32 {
219
- self . angle * self . radius
228
+ self . angle ( ) * self . radius
220
229
}
221
230
222
231
/// Get the start point of the arc
@@ -228,7 +237,7 @@ impl Arc {
228
237
/// Get the end point of the arc
229
238
#[ inline( always) ]
230
239
pub fn end ( & self ) -> Vec2 {
231
- self . radius * Vec2 :: from_angle ( self . angle )
240
+ self . radius * Vec2 :: from_angle ( self . angle ( ) )
232
241
}
233
242
234
243
/// Get the endpoints of the arc
@@ -237,34 +246,57 @@ impl Arc {
237
246
[ self . start ( ) , self . end ( ) ]
238
247
}
239
248
249
+ /// Get the midpoint of the arc
250
+ #[ inline]
251
+ pub fn midpoint ( & self ) -> Vec2 {
252
+ self . radius * Vec2 :: from_angle ( self . half_angle )
253
+ }
254
+
240
255
/// Get half the length of the chord subtended by the arc
241
256
#[ inline( always) ]
242
- pub fn half_chord_length ( & self ) -> f32 {
243
- self . radius * f32:: sin ( self . angle / 2.0 )
257
+ pub fn half_chord_len ( & self ) -> f32 {
258
+ self . radius * f32:: sin ( self . half_angle )
244
259
}
245
260
246
261
/// Get the length of the chord subtended by the arc
247
262
#[ inline( always) ]
248
- pub fn chord_length ( & self ) -> f32 {
249
- 2.0 * self . half_chord_length ( )
263
+ pub fn chord_len ( & self ) -> f32 {
264
+ 2.0 * self . half_chord_len ( )
250
265
}
251
266
252
- /// Get the distance from the center of the circle to the midpoint of the chord.
267
+ /// Get the midpoint of the chord
253
268
#[ inline( always) ]
254
- pub fn chord_midpoint_radius ( & self ) -> f32 {
255
- f32 :: sqrt ( self . radius . powi ( 2 ) - self . half_chord_length ( ) . powi ( 2 ) )
269
+ pub fn chord_midpoint ( & self ) -> Vec2 {
270
+ self . apothem_len ( ) * Vec2 :: from_angle ( self . half_angle )
256
271
}
257
272
258
- /// Get the midpoint of the chord
273
+ /// Get the length of the apothem of this arc, that is,
274
+ /// the distance from the center of the circle to the midpoint of the chord.
275
+ /// Equivalently, the height of the triangle whose base is the chord and whose apex is the center of the circle.
259
276
#[ inline( always) ]
260
- pub fn chord_midpoint ( & self ) -> Vec2 {
261
- Vec2 :: new ( self . chord_midpoint_radius ( ) , 0.0 ) . rotate ( Vec2 :: from_angle ( self . angle ) )
277
+ pub fn apothem_len ( & self ) -> f32 {
278
+ f32:: sqrt ( self . radius . powi ( 2 ) - self . half_chord_len ( ) . powi ( 2 ) )
279
+ }
280
+
281
+ /// Get the legnth of the sagitta of this arc, that is,
282
+ /// the length of the line between the midpoints of the arc and its chord.
283
+ /// Equivalently, the height of the triangle whose base is the chord and whose apex is the midpoint of the arc.
284
+ ///
285
+ /// If the arc is minor, i.e. less than half the circle, the this will be the difference of the [radius](Self::radius) and the [apothem](Self::apothem).
286
+ /// If it is [major](Self::major), it will be their sum.
287
+ #[ inline( always) ]
288
+ pub fn sagitta_len ( & self ) -> f32 {
289
+ if self . is_major ( ) {
290
+ self . radius + self . apothem_len ( )
291
+ } else {
292
+ self . radius - self . apothem_len ( )
293
+ }
262
294
}
263
295
264
296
/// Produces true if the arc is at least half a circle.
265
297
#[ inline( always) ]
266
298
pub fn is_major ( & self ) -> bool {
267
- self . angle >= PI
299
+ self . angle ( ) >= PI
268
300
}
269
301
}
270
302
@@ -276,40 +308,80 @@ impl Arc {
276
308
#[ derive( Clone , Copy , Debug , PartialEq ) ]
277
309
#[ cfg_attr( feature = "serialize" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
278
310
pub struct CircularSector {
279
- /// The radius of the circle
280
- pub radius : f32 ,
281
- /// The angle swept out by the sector.
282
- pub angle : f32 ,
311
+ /// The arc from which this sector is contructed.
312
+ #[ cfg_attr( feature = "seriealize" , serde( flatten) ) ]
313
+ pub arc : Arc ,
283
314
}
284
315
impl Primitive2d for CircularSector { }
285
316
286
317
impl Default for CircularSector {
287
318
// Returns the default [`CircularSector`] with radius `0.5` and angle `1.0`.
288
319
fn default ( ) -> Self {
289
- Self {
290
- radius : 0.5 ,
291
- angle : 1.0 ,
292
- }
320
+ Arc :: default ( ) . into ( )
321
+ }
322
+ }
323
+
324
+ impl From < Arc > for CircularSector {
325
+ fn from ( arc : Arc ) -> Self {
326
+ Self { arc }
293
327
}
294
328
}
295
329
296
330
impl CircularSector {
297
- /// Create a new [` CircularSector` ] from a `radius`, and an `angle`
331
+ /// Create a new [CircularSector] from a `radius`, and an `angle`
298
332
#[ inline( always) ]
299
- pub const fn new ( radius : f32 , angle : f32 ) -> Self {
300
- Self { radius, angle }
333
+ pub fn new ( radius : f32 , angle : f32 ) -> Self {
334
+ Arc :: new ( radius, angle) . into ( )
301
335
}
302
336
303
- /// Produces the arc of this sector
337
+ /// Returns the area of this sector
304
338
#[ inline( always) ]
305
- pub fn arc ( & self ) -> Arc {
306
- Arc :: new ( self . radius , self . angle )
339
+ pub fn area ( & self ) -> f32 {
340
+ self . arc . radius . powi ( 2 ) * self . arc . half_angle
307
341
}
342
+ }
308
343
309
- /// Returns the area of this sector
344
+ /// A primitive representing a circular segment:
345
+ /// the area enclosed by the arc of a circle and its chord (the line between its endpoints).
346
+ ///
347
+ /// The segment is drawn starting from [Vec2::X], going counterclockwise.
348
+ /// To orient the segment differently, apply a rotation.
349
+ /// The segment is drawn with the center of its circle at the origin (0, 0).
350
+ /// When positioning the segment, the [apothem_len](Self::apothem) and [sagitta_len](Sagitta) functions
351
+ /// may be particularly useful.
352
+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
353
+ #[ cfg_attr( feature = "serialize" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
354
+ pub struct CircularSegment {
355
+ /// The arc from which this segment is contructed.
356
+ #[ cfg_attr( feature = "seriealize" , serde( flatten) ) ]
357
+ pub arc : Arc ,
358
+ }
359
+ impl Primitive2d for CircularSegment { }
360
+
361
+ impl Default for CircularSegment {
362
+ // Returns the default [CircularSegment] with radius `0.5` and angle `1.0`.
363
+ fn default ( ) -> Self {
364
+ Arc :: default ( ) . into ( )
365
+ }
366
+ }
367
+
368
+ impl From < Arc > for CircularSegment {
369
+ fn from ( arc : Arc ) -> Self {
370
+ Self { arc }
371
+ }
372
+ }
373
+
374
+ impl CircularSegment {
375
+ /// Create a new [CircularSegment] from a `radius`, and an `angle`
376
+ #[ inline( always) ]
377
+ pub fn new ( radius : f32 , angle : f32 ) -> Self {
378
+ Arc :: new ( radius, angle) . into ( )
379
+ }
380
+
381
+ /// Returns the area of this segment
310
382
#[ inline( always) ]
311
383
pub fn area ( & self ) -> f32 {
312
- self . radius . powi ( 2 ) * self . angle / 2.0
384
+ self . arc . radius . powi ( 2 ) * ( self . arc . half_angle - self . arc . angle ( ) . sin ( ) )
313
385
}
314
386
}
315
387
0 commit comments