t-hom’s diary

主にVBAネタを扱っているブログです。

VBA 三角関数を用いて複数のオートシェイプを円周状に並べる

今回は三角関数を用いて複数のオートシェイプを円周状に並べるプログラムを作成したので備忘禄がてらサクッとご紹介。
目的はとあるゲームのためであるが、記事の本筋ではないのでそれは最後に紹介。

作ったもの

以下のように、正方形を円形に3周分並べた。

コード

※特定の目的のための使い捨てコードなので変数宣言は一部省略している箇所があります。

Sub LayoutRectangleAsCirculer()
    Const OFFSET_X = 200
    Const OFFSET_Y = 200
    Const SIZE = 14
    Dim r As Double: r = 100
    Dim sh As Shape
    Dim degree As Integer
    For i = 1 To 3
        For degree = 0 To 350 Step 10
            θ = Radian(degree)
            x = r * Sin(θ) + OFFSET_X - SIZE / 2
            y = r * Cos(θ) + OFFSET_Y - SIZE / 2
            cnt = cnt + 1
            Set sh = Sheet1.Shapes.AddShape _
                (msoShapeRectangle, x, y, SIZE, SIZE)
            sh.Rotation = 360 - degree
        Next
        r = r + SIZE + 1
    Next
End Sub

Function Radian(degree As Integer)
    Radian = degree / 45 * Atn(1)
End Function

説明

三角関数は高校1年で習う。ただ当時は使いどころが分からずただ闇雲に覚えさせられるだけという方も多いと思う。かくいう私も今年に入ってようやく意味を理解したところである。
今回は円周上にオートシェイプを配置したいのだが、半径Rは適当に決めるとしてそこから角度ごとのX・Y座標をどうやって求めるかがポイントになる。

そこで三角関数の出番だ。三角関数を使うと、直角三角形のうち90°以外の角度が一つ分かれば、それぞれの辺の比が求まる。

具体的には、
底辺X = r * Sin(θ)
高さY = r * Cos(θ)

となる。

あとはθをループで0°~360°まで、任意のステップで変化させていけば良い。
(0°と360°は同じになるので実際には360°手前までループさせる。)

三角関数の使いどころについて改めて感じること

高校で三角関数を習ったときは、「三角形の辺の比?興味ねぇ」という感じだった。
それからどこかで「三角関数を使うと円が描ける」という話を聞いたときも、「へぇ、それで?」という感想しか持っていなかった。円なんて、コンパス使えば描けるし、コンピューターならなおのこと。ペイントでもCADでもパワポでも、円描画機能なんて大抵の作図ソフトが標準装備しているからだ。

三角関数について本格的に学んだのは今年1月頃に学習していた材料力学に登場したためだ。
(当時は木工でちゃんと耐荷重計算した机を作ろうとしてた。それ自体は結局挫折したけど、得たものは大きい。)

それから、PS4のコントローラーのアナログスティックの押し込み角度の計算に応用できることを知って、こんな記事を書いた。
thom.hateblo.jp

それでもまぁ、作図に使うことは無いだろうと思っていたんだけど、今回たまたま表題の用件があって一瞬で閃いた。
もし三角関数を知らないままだったら、円のシェイプをガイドとして配置して、その上に手で並べていたと思う。
三角関数は超便利だし、アイデアの源泉にもなるということを改めて実感した。

今回プログラムを書いた個人的な目的

実は随分前から、Satisfactoryという工場建設ゲームにハマっていて、今ちょうど円形の原子力発電所を建設しているところである。
それで、大量の水をパイプラインで運んでこないといけないんだけど、下のマップのように海は東側に偏っていて、岩にぶつからずに延々と海側へ伸ばしていけるラインは4か所しかない。

1ラインでパイプ18本。これが4か所で計72本を360°均等に振り分ける為のパイプの引き方に悩んでいた。

上記で紹介したマップは有志が作ったツールで、ゲーム自体は以下の通りファーストパーソンビューなので、極太パイプ72本を干渉させずに4か所にまとめるのがとても苦労するのだ。

それで計画を立てるために以下のような図を用意してプランを立てたという顛末である。

色分けしたとおりにパイプを引き込んで、最終的にはこんな感じになった。


以上

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。