@@ -176,7 +176,9 @@ impl Circle {
176
176
}
177
177
}
178
178
179
- /// A primitive representing an arc: a segment of a circle.
179
+ const HALF_PI : f32 = PI / 2.0 ;
180
+
181
+ /// A primitive representing an arc between two points on a circle.
180
182
///
181
183
/// An arc has no area.
182
184
/// If you want to include the portion of a circle's area swept out by the arc,
@@ -189,35 +191,62 @@ impl Circle {
189
191
/// The arc is drawn with the center of its circle at the origin (0, 0),
190
192
/// meaning that the center may not be inside its convex hull.
191
193
#[ derive( Clone , Copy , Debug , PartialEq ) ]
194
+ #[ doc( alias( "CircularArc" , "CircleArc" ) ) ]
192
195
#[ cfg_attr( feature = "serialize" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
193
- pub struct Arc {
196
+ pub struct Arc2d {
194
197
/// The radius of the circle
195
198
pub radius : f32 ,
196
- /// Half the angle swept out by the arc.
199
+ /// Half the angle subtended by the arc.
197
200
pub half_angle : f32 ,
198
201
}
199
- impl Primitive2d for Arc { }
202
+ impl Primitive2d for Arc2d { }
200
203
201
- impl Default for Arc {
202
- /// Returns the default [`Arc `] with radius `0.5` and angle `1.0` .
204
+ impl Default for Arc2d {
205
+ /// Returns the default [`Arc2d `] with radius `0.5`, covering a quarter of a circle .
203
206
fn default ( ) -> Self {
204
207
Self {
205
208
radius : 0.5 ,
206
- half_angle : 0.5 ,
209
+ half_angle : PI / 4.0 ,
207
210
}
208
211
}
209
212
}
210
213
211
- impl Arc {
212
- /// Create a new [`Arc `] from a `radius`, and an `angle `
214
+ impl Arc2d {
215
+ /// Create a new [`Arc2d `] from a `radius`, and a `half_angle `
213
216
#[ inline( always) ]
214
- pub fn new ( radius : f32 , angle : f32 ) -> Self {
217
+ pub fn new ( radius : f32 , half_angle : f32 ) -> Self {
218
+ Self { radius, half_angle }
219
+ }
220
+
221
+ /// Create a new [`Arc2d`] from a `radius` and an `angle` in radians.
222
+ #[ inline( always) ]
223
+ pub fn from_radians ( radius : f32 , angle : f32 ) -> Self {
215
224
Self {
216
225
radius,
217
226
half_angle : angle / 2.0 ,
218
227
}
219
228
}
220
229
230
+ /// Create a new [`Arc2d`] from a `radius` and an angle in `degrees`.
231
+ #[ inline( always) ]
232
+ pub fn from_degrees ( radius : f32 , degrees : f32 ) -> Self {
233
+ Self {
234
+ radius,
235
+ half_angle : degrees. to_radians ( ) / 2.0 ,
236
+ }
237
+ }
238
+
239
+ /// Create a new [`Arc2d`] from a `radius` and a `fraction` of a circle.
240
+ ///
241
+ /// A `fraction` of 1.0 would be a whole circle; 0.5 would be a semicircle.
242
+ #[ inline( always) ]
243
+ pub fn from_fraction ( radius : f32 , fraction : f32 ) -> Self {
244
+ Self {
245
+ radius,
246
+ half_angle : fraction * PI ,
247
+ }
248
+ }
249
+
221
250
/// Get the angle of the arc
222
251
#[ inline( always) ]
223
252
pub fn angle ( & self ) -> f32 {
@@ -256,76 +285,89 @@ impl Arc {
256
285
257
286
/// Get half the length of the chord subtended by the arc
258
287
#[ inline( always) ]
259
- pub fn half_chord_len ( & self ) -> f32 {
288
+ pub fn half_chord_length ( & self ) -> f32 {
260
289
self . radius * f32:: sin ( self . half_angle )
261
290
}
262
291
263
292
/// Get the length of the chord subtended by the arc
264
293
#[ inline( always) ]
265
- pub fn chord_len ( & self ) -> f32 {
266
- 2.0 * self . half_chord_len ( )
294
+ pub fn chord_length ( & self ) -> f32 {
295
+ 2.0 * self . half_chord_length ( )
267
296
}
268
297
269
- /// Get the midpoint of the chord
298
+ /// Get the midpoint of the chord subtended by the arc
270
299
#[ inline( always) ]
271
300
pub fn chord_midpoint ( & self ) -> Vec2 {
272
- self . apothem_len ( ) * Vec2 :: from_angle ( self . half_angle )
301
+ self . apothem ( ) * Vec2 :: from_angle ( self . half_angle )
273
302
}
274
303
275
304
/// Get the length of the apothem of this arc, that is,
276
305
/// the distance from the center of the circle to the midpoint of the chord.
277
306
/// Equivalently, the height of the triangle whose base is the chord and whose apex is the center of the circle.
278
307
#[ inline( always) ]
279
- pub fn apothem_len ( & self ) -> f32 {
280
- f32:: sqrt ( self . radius . powi ( 2 ) - self . half_chord_len ( ) . powi ( 2 ) )
308
+ // Naming note: Various sources are inconsistent as to whether the apothem is the segment between the center and the
309
+ // midpoint of a chord, or the length of that segment. Given this confusion, we've opted for the definition
310
+ // used by Wolfram MathWorld, which is the distance rather than the segment.
311
+ pub fn apothem ( & self ) -> f32 {
312
+ f32:: sqrt ( self . radius . powi ( 2 ) - self . half_chord_length ( ) . powi ( 2 ) )
281
313
}
282
314
283
315
/// Get the legnth of the sagitta of this arc, that is,
284
316
/// the length of the line between the midpoints of the arc and its chord.
285
317
/// Equivalently, the height of the triangle whose base is the chord and whose apex is the midpoint of the arc.
286
318
///
287
- /// If the arc is minor, i.e. less than half the circle, the this will be the difference of the [`radius`](Self::radius)
288
- /// and the [`apothem`](Self::apothem_len ).
319
+ /// If the arc is [ minor](Self::is_minor) , i.e. less than or equal to a semicircle,
320
+ /// this will be the difference of the [`radius`](Self::radius) and the [`apothem`](Self::apothem ).
289
321
/// If the arc is [major](Self::is_major), it will be their sum.
290
322
#[ inline( always) ]
291
- pub fn sagitta_len ( & self ) -> f32 {
323
+ pub fn sagitta ( & self ) -> f32 {
292
324
if self . is_major ( ) {
293
- self . radius + self . apothem_len ( )
325
+ self . radius + self . apothem ( )
294
326
} else {
295
- self . radius - self . apothem_len ( )
327
+ self . radius - self . apothem ( )
296
328
}
297
329
}
298
330
331
+ /// Produces true if the arc is at most half a circle.
332
+ ///
333
+ /// **Note:** This is not the negation of [`is_major`](Self::is_major): an exact semicircle is both major and minor.
334
+ #[ inline( always) ]
335
+ pub fn is_minor ( & self ) -> bool {
336
+ self . half_angle <= HALF_PI
337
+ }
338
+
299
339
/// Produces true if the arc is at least half a circle.
340
+ ///
341
+ /// **Note:** This is not the negation of [`is_minor`](Self::is_minor): an exact semicircle is both major and minor.
300
342
#[ inline( always) ]
301
343
pub fn is_major ( & self ) -> bool {
302
- self . angle ( ) >= PI
344
+ self . half_angle >= HALF_PI
303
345
}
304
346
}
305
347
306
348
/// A primitive representing a circular sector: a pie slice of a circle.
307
349
///
308
350
/// The sector is drawn starting from [`Vec2::X`], going counterclockwise.
309
351
/// To orient the sector differently, apply a rotation.
310
- /// The sector is drawn with the center of its circle at the origin (0, 0) .
352
+ /// The sector is drawn with the center of its circle at the origin [`Vec2::ZERO`] .
311
353
#[ derive( Clone , Copy , Debug , PartialEq ) ]
312
354
#[ cfg_attr( feature = "serialize" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
313
355
pub struct CircularSector {
314
356
/// The arc from which this sector is contructed.
315
- #[ cfg_attr( feature = "seriealize " , serde( flatten) ) ]
316
- pub arc : Arc ,
357
+ #[ cfg_attr( feature = "serialize " , serde( flatten) ) ]
358
+ pub arc : Arc2d ,
317
359
}
318
360
impl Primitive2d for CircularSector { }
319
361
320
362
impl Default for CircularSector {
321
- /// Returns the default [`CircularSector`] with radius `0.5` and angle `1.0` .
363
+ /// Returns the default [`CircularSector`] with radius `0.5` and covering a quarter circle .
322
364
fn default ( ) -> Self {
323
- Arc :: default ( ) . into ( )
365
+ Self :: from ( Arc2d :: default ( ) )
324
366
}
325
367
}
326
368
327
- impl From < Arc > for CircularSector {
328
- fn from ( arc : Arc ) -> Self {
369
+ impl From < Arc2d > for CircularSector {
370
+ fn from ( arc : Arc2d ) -> Self {
329
371
Self { arc }
330
372
}
331
373
}
@@ -334,7 +376,27 @@ impl CircularSector {
334
376
/// Create a new [`CircularSector`] from a `radius`, and an `angle`
335
377
#[ inline( always) ]
336
378
pub fn new ( radius : f32 , angle : f32 ) -> Self {
337
- Arc :: new ( radius, angle) . into ( )
379
+ Self :: from ( Arc2d :: new ( radius, angle) )
380
+ }
381
+
382
+ /// Create a new [`CircularSector`] from a `radius` and an `angle` in radians.
383
+ #[ inline( always) ]
384
+ pub fn from_radians ( radius : f32 , angle : f32 ) -> Self {
385
+ Self :: from ( Arc2d :: from_radians ( radius, angle) )
386
+ }
387
+
388
+ /// Create a new [`CircularSector`] from a `radius` and an angle in `degrees`.
389
+ #[ inline( always) ]
390
+ pub fn from_degrees ( radius : f32 , degrees : f32 ) -> Self {
391
+ Self :: from ( Arc2d :: from_degrees ( radius, degrees) )
392
+ }
393
+
394
+ /// Create a new [`CircularSector`] from a `radius` and a `fraction` of a circle.
395
+ ///
396
+ /// A `fraction` of 1.0 would be a whole circle; 0.5 would be a semicircle.
397
+ #[ inline( always) ]
398
+ pub fn from_fraction ( radius : f32 , fraction : f32 ) -> Self {
399
+ Self :: from ( Arc2d :: from_fraction ( radius, fraction) )
338
400
}
339
401
340
402
/// Returns the area of this sector
@@ -349,27 +411,27 @@ impl CircularSector {
349
411
///
350
412
/// The segment is drawn starting from [`Vec2::X`], going counterclockwise.
351
413
/// To orient the segment differently, apply a rotation.
352
- /// The segment is drawn with the center of its circle at the origin (0, 0) .
353
- /// When positioning the segment, the [`apothem_len `](Arc::apothem_len) and [`sagitta_len`](Arc::sagitta_len) functions
354
- /// may be particularly useful .
414
+ /// The segment is drawn with the center of its circle at the origin [`Vec2::ZERO`] .
415
+ /// When positioning a segment, the [`apothem `](Arc2d::apothem) function may be particularly useful,
416
+ /// as it computes the distance between the segment and the origin .
355
417
#[ derive( Clone , Copy , Debug , PartialEq ) ]
356
418
#[ cfg_attr( feature = "serialize" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
357
419
pub struct CircularSegment {
358
420
/// The arc from which this segment is contructed.
359
- #[ cfg_attr( feature = "seriealize " , serde( flatten) ) ]
360
- pub arc : Arc ,
421
+ #[ cfg_attr( feature = "serialize " , serde( flatten) ) ]
422
+ pub arc : Arc2d ,
361
423
}
362
424
impl Primitive2d for CircularSegment { }
363
425
364
426
impl Default for CircularSegment {
365
- /// Returns the default [`CircularSegment`] with radius `0.5` and angle `1.0` .
427
+ /// Returns the default [`CircularSegment`] with radius `0.5` and covering a quarter circle .
366
428
fn default ( ) -> Self {
367
- Arc :: default ( ) . into ( )
429
+ Self :: from ( Arc2d :: default ( ) )
368
430
}
369
431
}
370
432
371
- impl From < Arc > for CircularSegment {
372
- fn from ( arc : Arc ) -> Self {
433
+ impl From < Arc2d > for CircularSegment {
434
+ fn from ( arc : Arc2d ) -> Self {
373
435
Self { arc }
374
436
}
375
437
}
@@ -378,7 +440,27 @@ impl CircularSegment {
378
440
/// Create a new [`CircularSegment`] from a `radius`, and an `angle`
379
441
#[ inline( always) ]
380
442
pub fn new ( radius : f32 , angle : f32 ) -> Self {
381
- Arc :: new ( radius, angle) . into ( )
443
+ Self :: from ( Arc2d :: new ( radius, angle) )
444
+ }
445
+
446
+ /// Create a new [`CircularSegment`] from a `radius` and an `angle` in radians.
447
+ #[ inline( always) ]
448
+ pub fn from_radians ( radius : f32 , angle : f32 ) -> Self {
449
+ Self :: from ( Arc2d :: from_radians ( radius, angle) )
450
+ }
451
+
452
+ /// Create a new [`CircularSegment`] from a `radius` and an angle in `degrees`.
453
+ #[ inline( always) ]
454
+ pub fn from_degrees ( radius : f32 , degrees : f32 ) -> Self {
455
+ Self :: from ( Arc2d :: from_degrees ( radius, degrees) )
456
+ }
457
+
458
+ /// Create a new [`CircularSegment`] from a `radius` and a `fraction` of a circle.
459
+ ///
460
+ /// A `fraction` of 1.0 would be a whole circle; 0.5 would be a semicircle.
461
+ #[ inline( always) ]
462
+ pub fn from_fraction ( radius : f32 , fraction : f32 ) -> Self {
463
+ Self :: from ( Arc2d :: from_fraction ( radius, fraction) )
382
464
}
383
465
384
466
/// Returns the area of this segment
0 commit comments