わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

正五角形を描こう

 いきなりですが問題です.以下の図形を描いてください.画像の幅と高さは400ピクセル,線の太さは6ピクセルです.
f:id:takehikom:20210118055144p:plain
 さっそくですが解答です.次の内容を出力するプログラムを作ります.

<svg xmlns="http://www.w3.org/2000/svg" width="400px" height="400px">
<rect x="0" y="0" width="400" height="400" fill="cyan"/>
<polygon fill="orange" stroke="black" stroke-width="6" points="200.000,20.000 371.190,144.377 305.801,345.623 94.199,345.623 28.810,144.377 "/>
</svg>

 テキストエディタ(メモ帳,Notepad++など)を開いて上記をコピーし,名前を付けて保存する際に拡張子を「.svg」にすれば,出来上がったファイルをダブルクリックで,今どきのWindows PCならEdge上で画像が表示されます.Chromeなど他のブラウザで表示させたいときには,ブラウザへドラッグ&ドロップするよりは,SVGファイルを右クリックして「プログラムから開く」で選べば失敗しないはずです.
 「<svg」から始まるとおり,SVG画像です*1.プログラムで(C言語ならprintfで)テキストデータを適切に出力していくようにします.
 先週の授業(プログラミング活用2)の例題です.来年度以降も使用する可能性があるので,ソースコードそのものは載せませんが,C言語で記述する場合に注意することが2点,あります.一つは,printfを用いて「width="400px"」などに出現する2重引用符を出力したいときに,「printf("…width="400px"…");」と書いてはいけません.「printf("…width=\"400px\"…");」のように,出力したい2重引用符の前にバックスラッシュを入れます(「エスケープ」と呼ばれます).バックスラッシュを打ち込むには,日本語キーボードだと(日本語入力がオフの状態で)円記号です.
 もう一つはpoints属性の値となる「200.000,20.000 371.190,144.377 305.801,345.623 94.199,345.623 28.810,144.377 」の生成方法です.ここについて,printfによる出力を「<polygon fill="orange" stroke="black" stroke-width="6" points="」,points属性の値,「"/>」に3つに分け,points属性の値は,for文で出力させるとよいでしょう.polygon要素の出力のために,3つのprintf呼び出しを記述しますが,座標の出力は「for (i = 0; i < 5; i++)」の中で行います.
 値の最初の「200.000,20.000」は,画像中央の座標を(200,200)としたとき,そこから上に180だけ移動した座標と見ることができます.「371.190,144.377」は自明ではありませんが,中央を原点とする極座標で考えると,見えてきます.
f:id:takehikom:20210118055155j:plain
 ただしSVGの利用座標系*2に注意して,座標を求める必要もあります.簡単にいうと,左上が原点で,X座標は右(数学の慣例と同じ),Y座標は下(反対)にいくほど大きくなります.
 中心の座標は(\frac{w}{2},\frac{h}{2})で求められます.正d角形の各頂点は,その多角形の外接円の周上に,距離が均等になるようにd個の頂点をとります.今回,1個(最初)の座標を(200,20)とすると,残りの頂点の座標が,画像内の式の通りに求められます.数式をC言語の式に置き換えて,「×0」「×1」のところを「* i」にすればよいのです.
 授業では生成プログラムを「写経」させ,rの値を変更すれば大きさが変わることは自習(課題提出なし)としました.課題は,10点を結んだ星型になるよう,座標計算の処理を付け足してもらいました*3
 課題提出なしの自習をもとに,問題です.上の座標計算の画像で,「sin」と「cos」を入れ替えると,どのような図形が描かれるでしょうか?
 といったところで解答です.
f:id:takehikom:20210118055204p:plain
 もとの画像とどう変わったかについて,いろいろ説明ができますが,「90度回転」が最も簡潔ではないかと思います.数学における極座標系から直交座標系への変換では,x座標の計算にcos,y座標の計算にsinを使用するのが一般的*4ですが,プログラミングを通じて実際に描く場合には,注意が必要なところです.


 約4年前に,星形を描こうという記事をリリースしています.3年前期の授業の課題で,言語はJavaでした.もっとルーツをたどると,SVGで正多角形や星型を描くような,C言語による生成プログラムは,2003年度(2013年度ではなく)の授業で紹介していました.

*1:「<?xml ...?>」のXML宣言は,https://qiita.com/manabuyasuda/items/01a76204f97cd73ffc4eを読み,書かないことにしました.このページで必須とされている,svg要素のxmlns:xlinkとviewBoxの属性は,省略しました.

*2:https://triple-underscore.github.io/SVG11/coords.html#InitialCoordinateSystem

*3:points属性を"200.000,20.000 305.801,345.623 28.810,144.377 371.190,144.377 94.199,345.623 "と並べ替えることでも,星型が描けますが,これは資料に入れず,自習課題にもしませんでした.かわりに大小2つの円の周上5点ずつ,適切に頂点をとって結べば,星型が描けることを,資料画像で説明し,どこで小円上の頂点座標を計算し出力すればよいかを,考えてもらいました.

*4:授業の予習課題で調査してもらっていて,多くの学生が出典に挙げたのは,https://coinbaby8.com/polar-coordinates.htmlでした.