/
Circle.hpp
617 lines (493 loc) · 21.9 KB
/
Circle.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
//-----------------------------------------------
//
// This file is part of the Siv3D Engine.
//
// Copyright (c) 2008-2023 Ryo Suzuki
// Copyright (c) 2016-2023 OpenSiv3D Project
//
// Licensed under the MIT License.
//
//-----------------------------------------------
# pragma once
# include "Common.hpp"
# include "PointVector.hpp"
# include "ColorHSV.hpp"
# include "LineStyle.hpp"
# include "PredefinedYesNo.hpp"
namespace s3d
{
class Texture;
struct TextureRegion;
struct TexturedCircle;
/// @brief 円
struct Circle
{
using position_type = Vec2;
using size_type = position_type::value_type;
using value_type = position_type::value_type;
SIV3D_DISABLE_MSVC_WARNINGS_PUSH(4201)
union
{
/// @brief 円の中心座標
position_type center;
struct
{
/// @brief 円の中心の X 座標
value_type x;
/// @brief 円の中心の Y 座標
value_type y;
};
};
/// @brief 円の半径
/// @remark この値が負の時の挙動は未規定です。
size_type r;
SIV3D_DISABLE_MSVC_WARNINGS_POP()
/// @brief デフォルトコンストラクタ
SIV3D_NODISCARD_CXX20
Circle() = default;
/// @brief 中心が { 0, 0 } の円を作成します。
/// @param _r 円の半径
SIV3D_NODISCARD_CXX20
explicit constexpr Circle(size_type _r) noexcept;
/// @brief 中心が { 0, 0 } の円を作成します。
/// @param _r 円の半径
SIV3D_CONCEPT_ARITHMETIC
SIV3D_NODISCARD_CXX20
explicit constexpr Circle(Arithmetic _r) noexcept;
/// @brief 円を作成します。
/// @param _x 円の中心の X 座標
/// @param _y 円の中心の Y 座標
/// @param _r 円の半径
SIV3D_NODISCARD_CXX20
constexpr Circle(value_type _x, value_type _y, size_type _r) noexcept;
/// @brief 円を作成します。
/// @tparam X 引数の型
/// @tparam Y 引数の型
/// @tparam R 引数の型
/// @param _x 円の中心の X 座標
/// @param _y 円の中心の Y 座標
/// @param _r 円の半径
template <class X, class Y, class R>
SIV3D_NODISCARD_CXX20
constexpr Circle(X _x, Y _y, R _r) noexcept;
/// @brief 円を作成します。
/// @param _center 円の中心座標
/// @param _r 円の半径
SIV3D_NODISCARD_CXX20
constexpr Circle(position_type _center, size_type _r) noexcept;
/// @brief 円を作成します。
/// @param _center 円の中心座標
/// @param _r 円の半径
SIV3D_CONCEPT_ARITHMETIC
SIV3D_NODISCARD_CXX20
constexpr Circle(position_type _center, Arithmetic _r) noexcept;
/// @brief 円を作成します。
/// @param _center 円の中心座標
/// @param _r 円の半径
SIV3D_CONCEPT_ARITHMETIC
SIV3D_NODISCARD_CXX20
constexpr Circle(Arg::center_<position_type> _center, Arithmetic _r) noexcept;
/// @brief 円を作成します。
/// @param topLeft 円に外接する正方形の左上の座標
/// @param _r 円の半径
SIV3D_CONCEPT_ARITHMETIC
SIV3D_NODISCARD_CXX20
constexpr Circle(Arg::topLeft_<position_type> topLeft, Arithmetic _r) noexcept;
/// @brief 円を作成します。
/// @param topCenter 円に外接する正方形の上辺中心の座標
/// @param _r 円の半径
SIV3D_CONCEPT_ARITHMETIC
SIV3D_NODISCARD_CXX20
constexpr Circle(Arg::topCenter_<position_type> topCenter, Arithmetic _r) noexcept;
/// @brief 円を作成します。
/// @param topRight 円に外接する正方形の右上の座標
/// @param _r 円の半径
SIV3D_CONCEPT_ARITHMETIC
SIV3D_NODISCARD_CXX20
constexpr Circle(Arg::topRight_<position_type> topRight, Arithmetic _r) noexcept;
/// @brief
/// @param rightCenter
/// @param _r
SIV3D_CONCEPT_ARITHMETIC
SIV3D_NODISCARD_CXX20
constexpr Circle(Arg::rightCenter_<position_type> rightCenter, Arithmetic _r) noexcept;
/// @brief
/// @param bottomRight
/// @param _r
SIV3D_CONCEPT_ARITHMETIC
SIV3D_NODISCARD_CXX20
constexpr Circle(Arg::bottomRight_<position_type> bottomRight, Arithmetic _r) noexcept;
/// @brief
/// @param bottomCenter
/// @param _r
SIV3D_CONCEPT_ARITHMETIC
SIV3D_NODISCARD_CXX20
constexpr Circle(Arg::bottomCenter_<position_type> bottomCenter, Arithmetic _r) noexcept;
/// @brief
/// @param bottomLeft
/// @param _r
SIV3D_CONCEPT_ARITHMETIC
SIV3D_NODISCARD_CXX20
constexpr Circle(Arg::bottomLeft_<position_type> bottomLeft, Arithmetic _r) noexcept;
/// @brief
/// @param leftCenter
/// @param _r
SIV3D_CONCEPT_ARITHMETIC
SIV3D_NODISCARD_CXX20
constexpr Circle(Arg::leftCenter_<position_type> leftCenter, Arithmetic _r) noexcept;
/// @brief
/// @param p0
/// @param p1
SIV3D_NODISCARD_CXX20
Circle(position_type p0, position_type p1) noexcept;
/// @brief
/// @param p0
/// @param p1
/// @param p2
SIV3D_NODISCARD_CXX20
Circle(const position_type& p0, const position_type& p1, const position_type& p2) noexcept;
/// @brief
/// @param diameter
SIV3D_NODISCARD_CXX20
explicit Circle(const Line& diameter) noexcept;
/// @brief
/// @param _center
/// @param p
SIV3D_NODISCARD_CXX20
Circle(Arg::center_<position_type> _center, const position_type& p) noexcept;
[[nodiscard]]
friend constexpr bool operator ==(const Circle& lhs, const Circle& rhs) noexcept
{
return (lhs.center == rhs.center)
&& (lhs.r == rhs.r);
}
[[nodiscard]]
friend constexpr bool operator !=(const Circle& lhs, const Circle& rhs) noexcept
{
return (lhs.center != rhs.center)
|| (lhs.r != rhs.r);
}
constexpr Circle& set(value_type _x, value_type _y, size_type _r) noexcept;
constexpr Circle& set(position_type _center, size_type _r) noexcept;
constexpr Circle& set(Arg::center_<position_type> _center, size_type _r) noexcept;
constexpr Circle& set(Arg::topLeft_<position_type> topLeft, size_type _r) noexcept;
constexpr Circle& set(Arg::topCenter_<position_type> topCenter, size_type _r) noexcept;
constexpr Circle& set(Arg::topRight_<position_type> topRight, size_type _r) noexcept;
constexpr Circle& set(Arg::rightCenter_<position_type> rightCenter, size_type _r) noexcept;
constexpr Circle& set(Arg::bottomRight_<position_type> bottomRight, size_type _r) noexcept;
constexpr Circle& set(Arg::bottomCenter_<position_type> bottomCenter, size_type _r) noexcept;
constexpr Circle& set(Arg::bottomLeft_<position_type> bottomLeft, size_type _r) noexcept;
constexpr Circle& set(Arg::leftCenter_<position_type> leftCenter, size_type _r) noexcept;
constexpr Circle& set(const Circle& circle) noexcept;
constexpr Circle& setCenter(value_type _x, value_type _y) noexcept;
constexpr Circle& setCenter(position_type _center) noexcept;
constexpr Circle& setPos(value_type _x, value_type _y) noexcept;
constexpr Circle& setPos(position_type _center) noexcept;
constexpr Circle& setPos(Arg::center_<position_type> _center) noexcept;
constexpr Circle& setPos(Arg::topLeft_<position_type> topLeft) noexcept;
constexpr Circle& setPos(Arg::topCenter_<position_type> topCenter) noexcept;
constexpr Circle& setPos(Arg::topRight_<position_type> topRight) noexcept;
constexpr Circle& setPos(Arg::rightCenter_<position_type> rightCenter) noexcept;
constexpr Circle& setPos(Arg::bottomRight_<position_type> bottomRight) noexcept;
constexpr Circle& setPos(Arg::bottomCenter_<position_type> bottomCenter) noexcept;
constexpr Circle& setPos(Arg::bottomLeft_<position_type> bottomLeft) noexcept;
constexpr Circle& setPos(Arg::leftCenter_<position_type> leftCenter) noexcept;
constexpr Circle& setR(value_type _r) noexcept;
/// @brief 中心座標を移動した新しい円を返します。
/// @param _x X 軸方向の移動量
/// @param _y Y 軸方向の移動量
/// @return 新しい円
[[nodiscard]]
constexpr Circle movedBy(value_type _x, value_type _y) const noexcept;
/// @brief 中心座標を移動した新しい円を返します。
/// @param v 移動量
/// @return 新しい円
[[nodiscard]]
constexpr Circle movedBy(position_type v) const noexcept;
/// @brief 中心座標を移動させます。
/// @param _x X 軸方向の移動量
/// @param _y Y 軸方向の移動量
/// @return *this
constexpr Circle& moveBy(value_type _x, value_type _y) noexcept;
/// @brief 中心座標を移動させます。
/// @param v 移動量
/// @return *this
constexpr Circle& moveBy(position_type v) noexcept;
/// @brief 半径を変化させた新しい円を返します。
/// @param size 半径の変化量
/// @return 新しい円
[[nodiscard]]
constexpr Circle stretched(value_type size) const noexcept;
/// @brief X 軸、Y 軸上で径を変化させて楕円を作成します。
/// @param _x X 軸上の径の変化量
/// @param _y Y 軸上の径の変化量
/// @return 楕円
[[nodiscard]]
constexpr Ellipse stretched(double _x, double _y) const noexcept;
/// @brief 半径を拡大した新しい円を返します。
/// @param s 拡大倍率
/// @return 新しい円
[[nodiscard]]
constexpr Circle scaled(double s) const noexcept;
/// @brief X 軸、Y 軸上に拡大して楕円を作成します。
/// @param sx X 軸方向の拡大倍率
/// @param sy Y 軸方向の拡大倍率
/// @return 楕円
[[nodiscard]]
constexpr Ellipse scaled(double sx, double sy) const noexcept;
/// @brief 円周上で最も上にある点の座標を返します。
/// @return 最も上にある点の座標
[[nodiscard]]
constexpr position_type top() const noexcept;
/// @brief 円周上で最も右にある点の座標を返します。
/// @return 最も右にある点の座標
[[nodiscard]]
constexpr position_type right() const noexcept;
/// @brief 円周上で最も下にある点の座標を返します。
/// @return 最も下にある点の座標
[[nodiscard]]
constexpr position_type bottom() const noexcept;
/// @brief 円周上で最も左にある点の座標を返します。
/// @return 最も左にある点の座標
[[nodiscard]]
constexpr position_type left() const noexcept;
/// @brief X 軸に平行な直径(線分)を返します。
/// @return X 軸に平行な直径(線分)
[[nodiscard]]
constexpr Line horizontalDiameter() const noexcept;
/// @brief Y 軸に平行な直径(線分)を返します。
/// @return Y 軸に平行な直径(線分)
[[nodiscard]]
constexpr Line verticalDiameter() const noexcept;
/// @brief 円の面積を返します。
/// @return 円の面積
[[nodiscard]]
constexpr value_type area() const noexcept;
/// @brief 円の周の長さを返します。
/// @return 円の周の長さ
[[nodiscard]]
constexpr value_type perimeter() const noexcept;
/// @brief 円に外接する正方形を返します。
/// @return 円に外接する正方形
[[nodiscard]]
constexpr RectF boundingRect() const noexcept;
/// @brief 円周上の点をラジアン (12 時方向が 0, 3 時方向が π/2, 6 時方向が π) で取得します。
/// @param angle 方向(ラジアン)
/// @return 円周上の点
[[nodiscard]]
position_type getPointByAngle(double angle) const noexcept;
/// @brief 円から Polygon を作成します。
/// @param quality 品質
/// @return Polygon
[[nodiscard]]
Polygon asPolygon(uint32 quality = 24) const;
[[nodiscard]]
Polygon pieAsPolygon(double startAngle, double angle, uint32 quality = 24) const;
[[nodiscard]]
Polygon arcAsPolygon(double startAngle, double angle, double innerThickness, double outerThickness, uint32 quality = 24) const;
[[nodiscard]]
constexpr Circle lerp(const Circle& other, double f) const noexcept;
[[nodiscard]]
size_t hash() const noexcept;
template <class Shape2DType>
[[nodiscard]]
constexpr bool intersects(const Shape2DType& other) const;
template <class Shape2DType>
[[nodiscard]]
Optional<Array<Vec2>> intersectsAt(const Shape2DType& other) const;
template <class Shape2DType>
[[nodiscard]]
bool contains(const Shape2DType& other) const;
/// @brief 円が現在のフレームで左クリックされ始めたかを返します。
/// @return 円が現在のフレームで左クリックされ始めた場合 true, それ以外の場合は false
[[nodiscard]]
bool leftClicked() const noexcept;
/// @brief 円が左クリックされているかを返します。
/// @return 円が左クリックされている場合 true, それ以外の場合は false
[[nodiscard]]
bool leftPressed() const noexcept;
/// @brief 現在のフレームで円への左クリックが離されたかを返します。
/// @return 現在のフレームで円への左クリックが離された場合 true, それ以外の場合は false
[[nodiscard]]
bool leftReleased() const noexcept;
/// @brief 円が現在のフレームで右クリックされ始めたかを返します。
/// @return 円が現在のフレームで右クリックされ始めた場合 true, それ以外の場合は false
[[nodiscard]]
bool rightClicked() const noexcept;
/// @brief 円が右クリックされているかを返します。
/// @return 円が右クリックされている場合 true, それ以外の場合は false
[[nodiscard]]
bool rightPressed() const noexcept;
/// @brief 現在のフレームで円への右クリックが離されたかを返します。
/// @return 現在のフレームで円への右クリックが離された場合 true, それ以外の場合は false
[[nodiscard]]
bool rightReleased() const noexcept;
/// @brief 円上にマウスカーソルがあるかを返します。
/// @return 円上にマウスカーソルがある場合 true, それ以外の場合は false
[[nodiscard]]
bool mouseOver() const noexcept;
const Circle& paint(Image& dst, const Color& color, Antialiased antialiased = Antialiased::Yes) const;
const Circle& overwrite(Image& dst, const Color& color, Antialiased antialiased = Antialiased::Yes) const;
const Circle& paintFrame(Image& dst, double innerThickness, double outerThickness, const Color& color, Antialiased antialiased = Antialiased::Yes) const;
const Circle& overwriteFrame(Image& dst, double innerThickness, double outerThickness, const Color& color, Antialiased antialiased = Antialiased::Yes) const;
//const Circle& paintPie(Image& dst, double startAngle, double angle, const Color& color) const;
//const Circle& overwritePie(Image& dst, double startAngle, double angle, const Color& color) const;
//const Circle& paintArc(Image& dst, double startAngle, double angle, double innerThickness, double outerThickness, const Color& color) const;
//const Circle& overwriteArc(Image& dst, double startAngle, double angle, double innerThickness, double outerThickness, const Color& color) const;
/// @brief 円を描きます。
/// @param color 円の色
/// @return *this
const Circle& draw(const ColorF& color = Palette::White) const;
/// @brief 円を描きます。
/// @param innerColor 円の内側の色
/// @param outerColor 円の外側の色
/// @return *this
const Circle& draw(const ColorF& innerColor, const ColorF& outerColor) const;
/// @brief 円の枠を描きます
/// @param thickness 枠の太さ
/// @param color 枠の色
/// @return *this
const Circle& drawFrame(double thickness = 1.0, const ColorF& color = Palette::White) const;
/// @brief 円の枠を描きます
/// @param thickness 枠の太さ
/// @param innerColor 内側部分の枠の色
/// @param outerColor 外側部分の枠の色
/// @return *this
const Circle& drawFrame(double thickness, const ColorF& innerColor, const ColorF& outerColor) const;
/// @brief 円の枠を描きます。
/// @param innerThickness 基準の円から内側方向への枠の太さ
/// @param outerThickness 基準の円から外側方向への枠の太さ
/// @param color 枠の色
/// @return *this
const Circle& drawFrame(double innerThickness, double outerThickness, const ColorF& color = Palette::White) const;
/// @brief 円の枠を描きます。
/// @param innerThickness 基準の円から内側方向への枠の太さ
/// @param outerThickness 基準の円から外側方向への枠の太さ
/// @param innerColor 内側部分の枠の色
/// @param outerColor 外側部分の枠の色
/// @return *this
const Circle& drawFrame(double innerThickness, double outerThickness, const ColorF& innerColor, const ColorF& outerColor) const;
/// @brief 扇形を描きます。
/// @param startAngle 扇形の開始角度(ラジアン, 0 時の方向から時計回り)
/// @param angle 扇形の角度(ラジアン)
/// @param color 扇形の色
/// @return *this
const Circle& drawPie(double startAngle, double angle, const ColorF& color = Palette::White) const;
/// @brief 扇形を描きます。
/// @param startAngle 扇形の開始角度(ラジアン, 0 時の方向から時計回り)
/// @param angle 扇形の角度(ラジアン)
/// @param innerColor 扇の中心部分の色
/// @param outerColor 扇の外側部分の色
/// @return *this
const Circle& drawPie(double startAngle, double angle, const ColorF& innerColor, const ColorF& outerColor) const;
/// @brief 円の弧を描きます。
/// @param startAngle 弧の開始角度(ラジアン, 0 時の方向から時計回り)
/// @param angle 弧の角度(ラジアン)
/// @param innerThickness 基準の円から内側方向への弧の太さ
/// @param outerThickness 基準の円から外側方向への弧の太さ
/// @param color 弧の色
/// @return *this
const Circle& drawArc(double startAngle, double angle, double innerThickness = 1.0, double outerThickness = 0.0, const ColorF& color = Palette::White) const;
/// @brief 円の弧を描きます。
/// @param startAngle 弧の開始角度(ラジアン, 0 時の方向から時計回り)
/// @param angle 弧の角度(ラジアン)
/// @param innerThickness 基準の円から内側方向への弧の太さ
/// @param outerThickness 基準の円から外側方向への弧の太さ
/// @param innerColor 内側部分の弧の色
/// @param outerColor 外側部分の弧の色
/// @return *this
const Circle& drawArc(double startAngle, double angle, double innerThickness, double outerThickness, const ColorF& innerColor, const ColorF& outerColor) const;
/// @brief 円の弧を描きます。
/// @param style 線のスタイル
/// @param startAngle 弧の開始角度(ラジアン, 0 時の方向から時計回り)
/// @param angle 弧の角度(ラジアン)
/// @param innerThickness 基準の円から内側方向への弧の太さ
/// @param outerThickness 基準の円から外側方向への弧の太さ
/// @param color 弧の色
/// @return *this
const Circle& drawArc(const LineStyle& style, double startAngle, double angle, double innerThickness = 1.0, double outerThickness = 0.0, const ColorF& color = Palette::White) const;
/// @brief 円の弧を描きます。
/// @param style 線のスタイル
/// @param startAngle 弧の開始角度(ラジアン, 0 時の方向から時計回り)
/// @param angle 弧の角度(ラジアン)
/// @param innerThickness 基準の円から内側方向への弧の太さ
/// @param outerThickness 基準の円から外側方向への弧の太さ
/// @param innerColor 内側部分の弧の色
/// @param outerColor 外側部分の弧の色
/// @return *this
const Circle& drawArc(const LineStyle& style, double startAngle, double angle, double innerThickness, double outerThickness, const ColorF& innerColor, const ColorF& outerColor) const;
/// @brief 弓形を描きます。
/// @param arcMidpointAngle 弓形の弧の中心を円の中心から見た角度(ラジアン, 0 時の方向から時計回り)
/// @param height 弓形の高さ
/// @param color 色
/// @return *this
const Circle& drawSegment(double arcMidpointAngle, double height, const ColorF& color = Palette::White) const;
/// @brief 弓形を描きます。
/// @param startAngle 弓形の弧の開始角度(ラジアン, 0 時の方向から時計回り)
/// @param angle 弓形の弧の角度(ラジアン)
/// @param color 色
/// @return *this
const Circle& drawSegmentFromAngles(double startAngle, double angle, const ColorF& color = Palette::White) const;
/// @brief 円の影を描きます。
/// @param offset 影の位置のオフセット
/// @param blur ぼかしの大きさ(ピクセル)
/// @param spread 影の膨張(ピクセル)
/// @param color 影の色
/// @return *this
const Circle& drawShadow(const Vec2& offset, double blur, double spread = 0.0, const ColorF& color = ColorF{ 0.0, 0.5 }) const;
[[nodiscard]]
TexturedCircle operator ()(const Texture& texture) const;
[[nodiscard]]
TexturedCircle operator ()(const TextureRegion& textureRegion) const;
template <class CharType>
friend std::basic_ostream<CharType>& operator <<(std::basic_ostream<CharType>& output, const Circle& value)
{
return output << CharType('(')
<< value.x << CharType(',') << CharType(' ')
<< value.y << CharType(',') << CharType(' ')
<< value.r << CharType(')');
}
template <class CharType>
friend std::basic_istream<CharType>& operator >>(std::basic_istream<CharType>& input, Circle& value)
{
CharType unused;
return input >> unused
>> value.x >> unused
>> value.y >> unused
>> value.r >> unused;
}
friend void Formatter(FormatData& formatData, const Circle& value);
};
}
template <>
struct SIV3D_HIDDEN fmt::formatter<s3d::Circle, s3d::char32>
{
std::u32string tag;
auto parse(basic_format_parse_context<s3d::char32>& ctx)
{
return s3d::detail::GetFormatTag(tag, ctx);
}
template <class FormatContext>
auto format(const s3d::Circle& value, FormatContext& ctx)
{
if (tag.empty())
{
return format_to(ctx.out(), U"({}, {}, {})", value.x, value.y, value.r);
}
else
{
const std::u32string format
= (U"({:" + tag + U"}, {:" + tag + U"}, {:" + tag + U"})");
return format_to(ctx.out(), format, value.x, value.y, value.r);
}
}
};
template <>
struct std::hash<s3d::Circle>
{
[[nodiscard]]
size_t operator ()(const s3d::Circle& value) const noexcept
{
return value.hash();
}
};