切り出したドーナツ型の描画

Siv3D Advent Calender 2024 21日目の記事です

まずこの形をなんと呼ぶべきか

この形
本日の図形

この形だ。なんと呼べばいいのか、正式名称がないのだ。

ドーナツ型を切り出した図形と呼べるが、そう思っている人ばかりではあるまい。

ただの円を切り出したものであれば「扇形」という立派な名前があるのだが、これは数学の定義上の扇形ではない。

「でも扇ってこういう形してるしドーナツ型の切り出しも扇形呼んでもよくない?」とは思う。

ドローソフトを使って作った扇。下手か?

Siv3Dでの切り出したドーナツ型の描画

Siv3D切り出したドーナツ型を描画するのはCircle.drawPieメソッドでは実現できない。空隙を指定することはできないからだ。

しかし実際のところは分厚い弧を描く形を取ることで、そう苦労せず描画できる。
これにはCircle.drawArcメソッドを使う。

図形の塗りを描くのならそれで済むのだが、境界線を描きたい場合、rawPieやdrawArcの返り値はCircleなので、これにdrawFrameを使うと基準となる円の外周を描くだけになってしまう。

circle.drawArc(0_deg, 90_deg, 20, 0, Palette::White).drawFrame(8, Palette::Red);

境界線を描きたい場合は以下に2通りになりそうだ。

普通は(A)のやり方を取るだろう。線を図形にするのがポイントだ。


        double angle1 = 0_deg;
        double angle2 = 90_deg;
        double line_thickness = 10;

        circle.arcAsPolygon(angle1, angle2, 150, 0)..drawFrame(line_thickness, Palette::Orange);
      

(B)は地道に描画するのでそれぞれの線の色を変えることができる。
OffsetCircularで角度と距離を指定すれば特定位置からそれだけ離れた座標を取得できるので、意外とそこまで面倒ではない。
ちなみに弧の描画で内側と外側を同じ太さにしないときれいにならない。


        double angle1 = 0_deg;
        double angle2 = 90_deg;
        double line_thickness = 10;

        circle.drawArc(angle1, angle2, line_thickness / 2, line_thickness / 2, Palette::Green);
        circle2.drawArc(angle1, angle2, line_thickness / 2, line_thickness / 2, Palette::Orange);
        Line(OffsetCircular(circle.center, circle.r, angle1), OffsetCircular(circle.center, circle2.r, angle1)).draw(line_thickness,Palette::Orange);
        Line(OffsetCircular(circle.center, circle.r, angle2), OffsetCircular(circle.center, circle2.r, angle2)).draw(line_thickness, Palette::Orange);
        
かぼちゃの煮つけにピッタリ!

この図形の用途

かぼちゃの煮つけにも使えないことはないが、ゲーム等での用途はほぼパイメニュー(円状のメニュー)に絞られると思われる。

パイメニューについては公式でコードを出しているのでそちらも役に立つだろう。

手作りで実装する場合はきれいに見せるのにコツがある。

例えば4分割のメニューを作るとして、「87度+隙間3度で作ろう」とやると以下のようなものが出来上がって、メニューUIとしてはちょっと違うなという感じになる。

模様としてはいいけど

そのため一旦隙間のないように切り出しドーナツを敷き詰めてから、それぞれを少し散開させるようにするときれいに見えるだろう。

あまり離しすぎると中心の円が歪に見えるので注意

描線に影をつけたい場合、一旦レンダーテクスチャに完成形を作っておいて、そのテクスチャをdrawする方法が無難だと思うが、
場合によっては予め画像ファイルを作ったほうが楽かもしれない。