カテゴリー別アーカイブ: プログラミング

Programing

奥の細道・序文を改訂

バ―ジョンアップ

「奥の細道・序文の朗読記事」をバージョンアップしました。ボランティアにより公開された朗読を使わせていただいていましたが、このたび、朗読参照として明示しました。その他、細かな箇所が改訂されています。

吟遊詩人

吟遊詩人と言えば、中世ヨーロッパにおける高貴な宮廷婦人の恋愛を歌った抒情詩人を思い浮かべますが、芭蕉の句に『蚤虱(のみしらみ) 馬(うま)の尿(ばり)する 枕(まくら)もと』があります。花鳥風月を慈しんだ素朴な歌人の人柄がしのばれます。

奥の細道・序文の朗読

つき百代はくたい過客かかくにして、きかふとし又旅人也またたびびとなりふねうえ生涯しょうがいをうかべ、うまくちとらえておいをむかふるものは、たびにしてたびすみかとす。古人こじんおおたびせるあり。
もいづれのとしよりか、片雲へんうんかぜにさそはれて、漂泊ひょうはくおもひやまず、海浜かいひんにさすらへ、去年こぞあき江上こうしょう破屋はおくくも古巣ふるすをはらひて、
ややとしくれ春立はるたてかすみそら白河しらかわせきこえんと、そぞろがみものにつきてこころをくるはせ、道祖神どうそじんまねきにあひて、とるものにつかず。
ももひきやぶれをつづり、かさつけかえて、三里さんりきゅうすゆるより、松島まつしま月先心つきまずこころにかかりて、すめかたひとゆずり、杉風さんぷう別墅べっしょうつるに、
 くさ住替すみかわぞひなのいえ
面八句おもてはちくいおりはしらにかけく。
芭蕉     曽良
©TacM,2017 Ver0.03
 月日は永遠に旅を続ける旅人であり、来ては去り、去っては来る年もまた同じように旅人である。船頭として船の上に生涯を浮かべ、馬子として馬のくつわを引いて老いを迎える者は、毎日旅をして旅をすみかとしている。古人の中には旅の途中で命を無くした風流人が多くいる。
 私もいつの年からか、ちぎれ雲が風に吹かれて漂うように誘惑されて、旅に出て歩きたい気持ちが我慢できず、海や浜辺をさすらい、去年の秋、隅田川の畔を破れ小屋において蜘蛛の巣を取り払って暮らしているうちに、次第にその年も暮れ、春になり霞(かすみ)が立ち込める空を見るにつけても、あの名高い白河の関を越えようと、人の心をそわそわさせる神が取り付いて私の心を狂わせ、道祖神が招くような気がして取るものも手につかない。
 旅行着の破れ目を直し、笠の紐(ひも)を付け替えて、足に灸をすえると、あの有名な松島の月の美しさが真っ先に気にかかって、住んでいる家は他人に売り、杉風の別宅に引越しする時に、句を詠んだ。「草の戸も」の句を発句とする連句の初めの8句を草庵の柱に掛けておく。(現代語訳)

 

マチンの公式で円周率

近似式

円周率を求める式の研究は古来から盛んです。今からでも遅くはなく、収束が速い簡潔な式を見つければ、歴史に名を留めるかも知れません。今回は、今でも円周率の計算に使われるマチンの公式を使ってみます。

収束が速い

マチンの公式はとにかく、収束の速い式です。プログラミングは「マチンの公式」ウィキペデア《マチンの公式による計算》を参考にさせて頂きました。arctan(1/5)とarctan(1/239)において、両者の偏角値に開きがあり、計算する項数を調整しています。

小数点以下、14桁まで、多くの算出法と同じ値が得られました。ひところ、算出桁数を競った時期があり、2016年に22.4兆桁の記録があります。

サンプルコード

<div id="pic0" style="width:580px; height:265px;">
<img src="http://aidesign.lolipop.jp/wp-content/uploads/2017/06/MachinFormula.png"></div>
<script type="text/javascript" charset="Shift_JIS">
const c5_239 = [0.2, 1/239];
const multiple = [16, 4];
  var s = "マチンの公式を用いて円周率を算出<BR>"
  document.write(s);
  for(var j=0; j<=9; ++j){
    var u = arctan(j, 0) - arctan(j, 1);
    s = "m="+j+" 項数="+("0"+(4*j+4)).slice(-2)+" PI="+u+"<BR>";
    document.write(s);   /* 円周率を計算・出力 */
  }
function arctan(m, num){    // 逆正接を求める
  var v = 0;
  var s = 1;
  var w = num * 4;          // 0, 1 ---> 0, 4
  c = c5_239[num];
  for(var n=1; n<=(6-w)*m+5-w; n+=2){    // 0:6*m+5, 1:2*m+1
    var g = Math.pow(c, n);
    v += s * g / n;
    s = -s;
    //console.log("N="+n+" V="+v+" G="+g);
  }
  v *= multiple[num];
  return v;
}
</script>
</html>

実行結果

余談

document.write()の引数に式を指定すると文法エラーになり困りました。直前に変数に代入し、その変数を引数にすればエラーになりません。

 

ライプニッツ公式による

ライプニッツの公式により円周率を算出

前回、乱数を用いて円周率を求めました。精度の高い円周率を求める方法は乱数を用いません。「乱数を用いて円周率を求められますよ」ということを図を使って解説してあります。

一様にばらつく乱数を使うことが基本で、偏った乱数では実態に即した円周率は求まりません。一般に乱数関数は言語処理系が持っているので精度の高い円周率を求めるには他力本願にならざるを得ません。

自力本願による解決

円周率を求める無限級数の近似式はたくさんあります。近似式は規則性があり、繰り返し処理で算出可能です。小さい繰り返し回数で精度の高い値を求めることを収束が速い算出法と表現します。収束が速くはありませんが、式がシンプルで有名なライプニッツの公式があります。

総和記号の式を大きく明示すると以下の図のようになります。

今回はこれを使って円周率を求めてみます。古くはFORTRAN、BASIC、Cなどで取り上げられていますのでJavaScriptで記述したプログラミングコードを解説します。

プログラミングコード

<html>
<script type="text/javascript" charset="Shift_JIS">
// ライプニッツの公式を用いて円周率を算出する
const MAX = 50000;              //繰り返し回数
const DIFFERENCE = (0.0001/4);  //差分による収束判定値
var pi4 = 0;                    //円周率格納変数
var previous = 0;               //直前の計算値
var delta;                      //差分

for(var n=1; n<MAX; n+=2){      //1, 3, 5, 7, 9, 11, 13
  pi4 -= (n % 4 - 2) / n;       //
  delta = previous - pi4;
  //console.log("N="+n+" PI="+(pi4*4)+" deleta="+delta);    /* 円周率を計算・出力(解析用) */
  if(Math.abs(delta) < DIFFERENCE) break;                   /* 収束 */
  previous = pi4;
}
  document.write("N="+n+" PI="+(pi4*4)+" delta="+delta);   /* 円周率を計算・出力 */
</script>
</html>

上の図に示した公式をJavaScriptでプログラミングしています。

ライプニッツの公式を凝視すると、各項の分子は1でその符号は正、負が交互に現れます。分母は初期値が1で、等差2の等差数列であることが分かります。このことからすると、繰り返しインデックスは1から始まり、増加値が2であることが望ましいと言えます。

11: pi4 -= (n % 4 – 2) / n; //pi4+= (2-(n % 4)) / n;

上の式は総和記号を実現させる式の肝部分です。総和記号を厳密に解釈すると右のような表現になるが、演算順序を変えると左のように少し単純化できます。

10行目のfor文で制御変数の初期値を1に、増分を2にしてあります。14行目であらかじめ設定した収束値になったかどうかを判断しています。

動作結果から

収束の速い近似式による収束のありさまを下図に示します。200回ほどの繰り返し回数で精度の良い円周率が求まっています。

今回の動作結果から判断すると、仮に設定した収束値が得られるまで20000回かかりました。やはり、収束が遅いことが明らかになりました。

3.1416まで算出するにはかなりの繰り返しが必要になります。



ライプニッツの公式は単純な規則性があり、サンプルとして取り上げられますが、円周率算出の本命とは言い難く、その席はマチンの公式などに譲ることになります。

乱数を用いて円周率算出

ゆとり教育

戦後の詰め込み教育を反省して、ゆとり教育が叫ばれた時期がありました。そのとき、小数演算は難しいので円周と直径の比率は3.14…のところ、3で計算してもよいという通達があったと聞きました。

これでは誤差が大きいのではと気をもんでいましたが、ゆとり教育そのものがとん挫したようです。

乱数を用いて円周率を算出

乱数を用いて円周率を算出する資料は、山のように溢れていますが、仕組みを解説している記事は多くありません。今回、図を描いて丁寧に説明をします。

乱数の種類

乱数には、自然乱数、一様乱数、正規乱数などがありますが、ここではある有限の区間を区切って、その区間内で全ての実数が同じ確率(濃度)で現れるような乱数である一様乱数を採用します。

今回、JavaScriptを使ってプログラミングしますが、一様乱数はMath.random関数が用意されています。

算出の仕組み

一様乱数は0~1(0 <= r < 1)の区間で、同じ確率で発生します。一辺が1の正方形の中に2つの乱数を発生させ、xとyに割り振るとP点が求まります。

そのP点が1/4円の中に入る確率は正方形と1/4円の面積比であるπ/4になります。算出した確率を4倍すれば円周率が求まる仕掛けです。

P点が1/4円の中にあるかどうかは、xとyから半径zを求め、その値が1以下ならば円内にあると判断します。

正方形の面積:1、1/4円の面積:π/4

正しくはx、yの二乗和の平方根の値を求めておく必要があるが、

a、bがともに正で、a<bならば√a<√b
の式が成り立つので平方根を求める必要はありません。

検証

正確な円周率に近づけるにはMAXの値を大きくしますが、この方法で精度の高い円周率を求めることはできません。精度の高い円周率を算出するにはマクロリーン級数による近似値計算などがあります。

サンプルコード

<html>
<script type="text/javascript" charset="Shift_JIS">
// 乱数を用いて円周率を算出する
const MAX = 1000000;
var count = 0;

for(var i=0; i<MAX; ++i){
	var x = Math.random();
	var y = Math.random();
	var z = x * x + y * y;
	if(z < 1) ++count;
}
  /* 円周率を計算・出力 */
  var pi = count / MAX * 4;
  alert("PI="+pi);
</script>
</html>

動作結果

さいごに

乱数を用いて円周率を算出してみました。紀元前2000年ころには古代バビロニアで22/7=3.142857が使われていたといいます。なんぼなんでもπ≒3は暴挙としか思えません。

 

都道府県を知ろう

1都1道2府43県

また、古い話で恐縮です。かつては車や新幹線などの交通機関が充実してないので、世界地図、日本地図への親しみが強かったように思います。

名曲「コンドルは飛んで行く」にあるように狭い大地に縛られることなく、自由に飛んでいきたいという欲求は誰にでもあります。郷愁をそそる名曲は『コンドルは飛んでいく』、『El Condor Pasa』で検索してお聞きください。

江戸時代のお伊勢参りのような無銭旅行もままならず、交通機関が充実しても即、自由に国内旅行を楽しむことは少なく、遠方への旅行ができるようになったのは、経済力が付いた後のことであり、そんなに時間は経っておりません。

今では、地図による予備知識の吸収に重きが置かれなくなったせいもあり、県の位置を正確に把握している人は昔より少ないように感じられます。そのぶん、生きた情報に触れる機会が多くなっています。

そこで、インターネットを利用して、県の位置、県名、県庁所在地名を始め、詳細な関連情報を取得するツールをJavaScriptで作ってみました。

使い方

小学生の地理の勉強に、47都道府県の場所と県名と県庁所在地名を覚えるには、地図上をクリックします。クリックする前に考えていたものと同じかどうかを確認します。県名の前に表示される2桁の番号は沖縄を0とし、北海道を46とする整理番号です。

同一箇所をさらにクリックすると県庁所在地名が表示され、もう一度クリックすると『〇〇県の詳細情報を表示するページにジャンプしますか?』という画面に切り替わります。OKの入力で別ページにジャンプし、戻るボタンをクリックすれば、当該ページに戻ってくることができます。

切り替えボタンをクリックすると47都道府県の県名が一斉に表示・非表示になります。

締めくくりの前に

因みに、県名と県庁所在地名が異なる県は、北海道と東京都を含めると19都道県になります。埼玉県はさいたま市が県庁所在地ですが、漢字とひらがなであり異なるものとしてカウントされています。

北国の人々は西国の地理に明るくなく、同様に西国の人々には北国の地理に暗いとされています。ゲーム感覚で地理や歴史、風土などについて調べてみましょう。

ソースコードは別の機会に、JavaScriptプログラミングの開発を解説する形で他も含めて一気に公開する予定です。

ちょっぴり高度な処理へ

2020年から小学校において、プログラミング教育が本格化します。

子供向けプログラミング言語としてScratch(スクラッチ)、Viscuit(ビスケット)があり、それらを使って県の特長や特産物の絵を表示するプログラムを小学2年生女子生徒が開発しています。頼もしいことです。

簡易言語では指定された県から詳細情報を引き出すことには難儀します。プログラミングを先導する先生にはJavaScriptのエッセンスは理解していただきたいものです。

動作例

 

 

 

JavaScript無名関数の文法

困った体験

最近、JavaScriptで無名関数を使い、思わぬ落とし穴にはまりそうになった体験談についてまとめます。古くからある言語は行単位で記述する習わしでした。

文の終わりは行末であるから、セミコロンのような文の終わりを明示しなくてもよかったのです。

新しい言語は行ではなく、ブロックという考え方に変わり、文の終わりにはセミコロンで区切るようになっています。

その名残りなのか、セミコロンを省略しても文法エラーとして扱わない温情ゆたかなブラウザが多いです。

4つの例題で確認

4つの例題を1つのファイルのまとめました。それぞれの特徴を記します。check0は無名関数の文法に則った記述です。check1は無名関数の終わりを示す’}’の後のセミコロンを省略したもの。check2は’}’の後の2つの改行コードを削除したもの。最後のcheck3は’}’の後にセミコロンを挿入したものです。

<!DOCTYPE html check0.html>
<html>
<script>
calc = function (a, b) {//結果を求め、戻り値を返す
	return a + b;
};						//<==== セミコロン
						//<<< 無名関数の動作確認 >>>
alert(calc(1, 2));		//3が出力される
alert(calc(10, 20));	//30が出力される
</script>
</html>
//----------------------------------------------------
<!DOCTYPE html check1.html>
<html>
<script>
calc = function (a, b) {//結果を求め、戻り値を返す
	return a + b;
}						//<==== セミコロン忘れ

alert(calc(1, 2));		//3が出力される
alert(calc(10, 20));	//30が出力される
</script>
</html>
//----------------------------------------------------
<!DOCTYPE html check2.html>
<html>
<script>
calc = function (a, b) {//結果を求め、戻り値を返す
	return a + b;
}alert(calc(1, 2));		//3が出力される(この行でエラー)
alert(calc(10, 20));	//30が出力される
</script>
</html>
//----------------------------------------------------
<!DOCTYPE html check3.html>
<html>
<script>
calc = function (a, b) {//結果を求め、戻り値を返す
	return a + b;
};alert(calc(1, 2));	//3が出力される(エラーは起きない)
alert(calc(10, 20));	//30が出力される
</script>
</html>

動作結果

check0 文法エラーなし
check1 文法エラーなし。18行の}の後、行末まで有効なコードがないのでセミコロンを自動補完
strict版check1 文法エラー発生
check2 文法エラー発生。30行、}の後に有効なコードがあるのでセミコロンは自動挿入されない
check3 文法エラーなし

厳密な文法チェック法

check1において、厳密な文法チェックをするには、”use strict”指定にします。すると「Uncaught ReferenceError: calc is not defined at check1.html:5」のエラーが出力されるようになります。以下に改訂されたcheck1を示します。

<!DOCTYPE html check1.html>
<html>
<script>
"use strict";
calc = function (a, b) {//結果を求め、戻り値を返す
	return a + b;
}

alert(calc(1, 2));		//3が出力される
alert(calc(10, 20));	//30が出力される
</script>
</html>

さいごに

曖昧なプログラミングでも文法エラーにしないで、期待通りに実行できることはありがたいことですが、check2のように冗長度をなくした時に、突然、エラーが検出されることがあります。

改行コードを削除して、ソースコードの解析されにくさをねらったときに、エラーが起きた場合には、厳格さを欠いたプログラミングを疑ってみましょう。

無名関数の定義は代入文と同等です。「代入文はセミコロンで締めくくる」と覚えておけば、セミコロンを忘れることが少なくなりそうです。

曖昧さを放っておくとセキュリティホールの原因になることがあります。できれば、曖昧な表現をなくしましょう。

 

時計と歯車の研究

理系の研究の一助に

2017年6月2日、日本の準天頂衛星「みちびき2号」の打ち上げ成功が伝えられました。何でもかんでも米国におんぶにだっこでは、経済的に優位を築いても難癖をつけられて譲歩を迫られてきました。多かれ少なかれこの傾向は果てしなく続くことでしょう。

そんな折、みちびき2号の打ち上げ成功は米軍のGPSから独立する糸口になることでしょう。一説によると位置検出の誤差は6㎝とも言われています。安定した打ち上げを行い、的確な運用には様々な分野の知識の結集が必要です。

ここでは紀元前はるか昔から存在する時計に目を向けてみます。

requestAnimationFrameの利用

スクリプト言語のJavaScriptにおいて、一定間隔で処理をするにはsetTimeout関数を使いますがここでは、requestAnimationFrame関数を使いました。

この関数はウインドウが非アクティブになると動作が低下ないし停止するので、メモリなどのコンピュータリソースの消費を抑えることができます。反面、バックグラウンドにおいて動作させたいときには不向きです。

Start Animationボタンをクリックして開始します。思うような動作にならない場合は、ブラウザをChromeかOperaに変えてみてください。

歯車の基本

歯車の歴史をたどるのも一つの楽しみかも知れません。向きを変えたり、減速、増速、間欠動作、反転、回転から直線運動など様々な使い方があります。

ここでは二つの歯車がかみ合ったとき、密着する歯数が同じになると想定しています。図面上に正しく歯数を表現することが難しいことから単純な円で表しています。

JavaScriptのSVG要素を用いた動作例を次に示しますが、右端の振り子は味付けの調味料です。冗長をお許しください。秒針の回転を、1/10、1/6の順に1/60に落とし、さらに分針の回転を、1/4、1/3の順に1/12に落としています。フクシアピンク色の#8、#4、#0の歯車が時分秒針に対応します。

動作例

 

 

縦書きを高級化する

縦書きの高級化・一般化

漢字文化圏では、縦書きがなくなることは少ないと思われます。かつて、大型コンピュータが普及し、事務計算、技術計算として重宝され始めました。手書きだった給与明細書の氏名欄がカタカナ表記になり、気の早い向きには漢字が消滅して、日本語はすべてカタカナになると論じていました。



そのような状況下でも、個人で手に入いるパソコンで漢字が使えるようになり、漢字処理の技術が確立しました。連綿と続いた文化は簡単には消え去るものではありません。その意味で、縦書きも高級化・一般化してこそ、晴れて市民権を得ると言えます。

その一つというにはチッポケですが、和歌の楽しみ方として、遅延表示をしながら音楽と画像を協同表現してみました。試みを以下に掲げます。

再読み込みボタンをクリックし、再実行して『桜と富士山の画像』の透過度が少しずつ変化する様に注目ください。

参照音楽:
【サイト名】フリー音楽素材 H/MIX GALLERY
【管理者】 秋山裕和
【アドレス】http://www.hmix.net/

サンプル表示


和歌を朗読のように
時間差で表示します
©TacM,2017 Ver0.01

 

縦書き遅延表示

縦書きのその後

詩、俳句、和歌などは縦書きが似合います。カラオケから縦書きの歌詞が流れると安らぎを感じます。

ブログやホームページにおいて縦書きをサポートするツール、h2vR.jsがリリースされ、多くの愛好家に使われています。

かつてから、縦書きで宮内庁が主催する歌会始の朗読のように、ちはやぶる……などと伸ばして遅延表示ができないかを検討しましたが、難解であるとの結論で保留していました。

setTimeout関数で処理を遅らせて非同期処理を試みましたが、思うようにはなりませんでした。

誤動作の内容

時間を遅らせて再度、innerHTMLにてデータを送ると、中間の進行中状態が表示されずに最後の状態だけが表示されたり、横書きになったりして期待した結果になりません。

試行錯誤を繰り返していると、縦書きと横書きを交互に切り替える方法を運営・管理サイトでJavaScriptコードを公開しており、切り替えた後にその都度、h2vR.switcher( … )関数を呼んでいることが分かりました。

遅延表示は切り替えではないのですが、縦書きの新しいデータを設定し直した後に、h2vR.switcher( … )関数を呼んだところ、こちらが期待した動作になりました。

以下に現代語訳と動作例を掲げます。

すでに実行中ですので、ロードボタンをクリックして、初めから表示してください。

現代語訳

わが家の庭にある、小さな竹林に吹く風の音が、かすかに聞こえるこの夕べかな。

実行例


©TacM,2017 Ver0.01 2017-04-08


和歌を朗読のように
時間差で表示します

 

Svgを用いた小作品

品質向上に寄与

商売を始めるにあたり、資金や労力が用意できれば十分というわけではありません。書類には表すことのできない、秘伝、ノウハウなど人知を超えたものが成功・不成功を決定づけることがあります。

JavaScriptを用いてHTML文書を作るにも、ツールを使って価値の高い文書に近づけます。

このたび、Svg要素で矢印付き円弧を含む図形を作成するための小さな道具を作りましたのでお知らせします。

Svgとは

Svg(Scalable Vector Graphics)はテキストを含めて、図形を表示するにあたり、すべて文字で表現するので、図形を拡大しても画面が粗くなることがありません。曲線や直線を表すには、豊富なコマンドを使います。コマンドはHTMLリファレンスマニュアルにしたがって作りますが思い通りになるとは限りません。

矢印の角度や長さが適切でないと寸胴のようで醜く、誤差で矢印が逆向きになることがあります。そこで動作を確認できるサポートツールを作りました。

矢印付き円弧を作る

矢印付きの円弧はpaint.netなどを使うと作成可能ですが、容易ではありません。今回のツールは描画するためのコマンドを仮に作り表示させます。

そのとき、そのコマンドをファイルに出力します。そして、満足のいく結果が得られたときに、ファイルにセーブしたコマンドをソースに反映します。console.logデバッグ文にてファイル出力を代替します。

コマンドをsvg要素のなかに設置すれば、JavaScriptを使わずにきれいな図形を描くことができます。上の図は今回のツールを用いて円弧に矢印を付けています。

サンプルコード

<html>
<head>
<svg width="500px" height="500px" version="2.0" xmlns="http://www.w3.org/2000/svg"  style="border:1px solid pink;">
<text x="5" y="16" font-family="sans-serif" font-size="12px" fill="navy">&copy;2017 TacM, Ver 0.01</text>
<marker viewBox="0 -3 10 10" refX="5" refY="0" orient="auto-start-reverse" markerWidth="10" markerHeight="10" id="mk1">
  <polygon points="10,0, 0,3 0,-3"/>
</marker>
<path id="cm0" d="M 430 246 A 180 180 0 0 0 343.46410161513774 96.11542731880104"
 fill="none" stroke="orange"	marker-start="url(#mk1)" marker-end="url(#mk1)"/>
<path id="cm1" d="M 336.53589838486226 92.11542731880104 A 180 180 0 0 0 82.22340883183918 184.67760371823599"
 fill="none" stroke="orange"	marker-start="url(#mk1)" marker-end="url(#mk1)"/>
<path id="cm2" d="M 79.48724768523383 192.19514468452323 A 180 180 0 0 0 214.80409700790372 426.5708028315297"
 fill="none" stroke="orange"	marker-start="url(#mk1)" marker-end="url(#mk1)"/>
<path id="cm3" d="M 222.68255903200136 427.9599882528652 A 180 180 0 0 0 430 254.0"
 fill="none" stroke="orange"	marker-start="url(#mk1)" marker-end="url(#mk1)"/>
	<path id="ln0" d="M 250 250 L 350 76.8" fill="none" stroke="green"/>
	<path id="ln1" d="M 250 250 L 62.06147584281834 181.59597133486622" fill="none" stroke="green"/>
	<path id="ln2" d="M 250 250 L 215.27036446661393 446.9615506024416" fill="none" stroke="green"/>
	<path id="ln3" d="M 250 250 L 450 250.0" fill="none" stroke="green"/>
<path d="M 0 250 L 500 250" stroke="aliceblue" fill="none" stroke-width="1"/>
<path d="M 250 0 L 250 500" stroke="aliceblue" fill="none" stroke-width="1"/>
</svg>
</head>
<body onLoad="rose1()"><BR>
開始角度<input id="step1" type="number" min="0" max="360" value="0" style="width:52px;"/>
終了角度<input id="step2" type="number" min="0" max="360" value="60" style="width:52px;"/>
矢印円径<input id="step3" type="number" min="40" max="120" value="72" style="width:52px;"/>
仕切り長<input id="step4" type="number" min="40" max="120" value="90" style="width:52px;"/>
<input id="msg3" type="button" onClick="display('step1', 'step2', 'step3', 'step4')" value="描画"
style="font-weight:bold; background-color:cyan; border-color:red; border-width:1px"/>
</body>
<script type="text/javascript" charset="Shift_JIS">
const COM1="M "; //
const COM2="A "; //
const ZX=250;
const ZY=250;

var count=0;
var RADIUS=72;
var LENGTH=90;
function rose1(){
	console.log("Start SvgArcGen.");
}
function display(target1, target2, target3, target4){   //描画ボタンが押下されたとき起動
 if(count >= 4) alert("終わっています");
 else{													//開始
  if(count==0){
	cm0.setAttribute("d", "");ln0.setAttribute("d", "");//#1
	cm1.setAttribute("d", "");ln1.setAttribute("d", "");//#2
	cm2.setAttribute("d", "");ln2.setAttribute("d", "");//#3
	cm3.setAttribute("d", "");ln3.setAttribute("d", "");//#4
  }
  var tg1 = document.getElementById(target1).value;     //ステッパー値を算出
  var tg2 = document.getElementById(target2).value;     //ステッパー値を算出
  RADIUS = document.getElementById(target3).value;      //ステッパー値を算出
  LENGTH = document.getElementById(target4).value;      //ステッパー値を算出
  var x1 = ZX+RADIUS * Math.cos(tg1 * Math.PI / 180);
  var y1 = ZY-RADIUS * Math.sin(tg1 * Math.PI / 180);
  var x2 = ZX+RADIUS * Math.cos(tg2 * Math.PI / 180);
  var y2 = ZY-RADIUS * Math.sin(tg2 * Math.PI / 180);

  var f2 = (tg2 - tg1) < 180 ? 0 : 1;

  var xb1 = 4 * Math.sin(tg1 * Math.PI / 180);
  var yb1 = 4 * Math.cos(tg1 * Math.PI / 180);
  var xb2 = 4 * Math.sin(tg2 * Math.PI / 180);
  var yb2 = 4 * Math.cos(tg2 * Math.PI / 180);

    var vx = ZX+LENGTH * Math.cos(tg2 * Math.PI / 180);
    var vy = ZY-LENGTH * Math.sin(tg2 * Math.PI / 180);
    //console.log("LX="+vx+" LY="+vy);

    var md1 = COM1 + (x1-xb1) + " " + (y1-yb1) + " ";
    var md2 = COM2 + RADIUS + " "+ RADIUS + " 0 ";
    var md3 = md1 + md2 + f2 + " 0 " + (x2+xb2) + " " + (y2+yb2);

    md2 = COM1 + ZX + " "+ ZY + " L " + vx + " " + vy;
    console.log("cm"+count+" : "+md3+"  ln"+count+" : "+md2);
	switch(count){
	case 0:	cm0.setAttribute("d", md3);ln0.setAttribute("d", md2);break;	//#1
	case 1:	cm1.setAttribute("d", md3);ln1.setAttribute("d", md2);break;	//#2
	case 2:	cm2.setAttribute("d", md3);ln2.setAttribute("d", md2);break;	//#3
	case 3:	cm3.setAttribute("d", md3);ln3.setAttribute("d", md2);break;	//#4
	}
	step1.setAttribute("value", tg2);										//開始角度
	var tg3 = (tg2 > 260) ? 360 : Number(tg2) + 100;
	step2.setAttribute("value", tg3);										//終了角度
	++count;
 }
}
</script>
</html>

実行例

©2017 TacM, Ver 0.01
開始角度 終了角度 矢印円径 仕切り長

コマンドの作り方

サンプルコードの3,5行目に示すように、Svgのバージョンは2.0でorient属性のパラメータはauto-start-reverse指定でなければなりません。開始角度、終了角度、矢印円径、仕切り長を入力して描画ボタンをクリックすると下図のような円弧と仕切り線が描画されます。

次の開始角度は前回の終了角度がコピーされます。よって、2回目以降、連続した領域に円弧を描くには終了角度だけを入力して描画ボタンをクリックします。描画は4回で終了になります。

デバッガを起動しconsole.logで出力したメッセージをコマンドに使えるように、コピー&ペーストで取り込み、テキストエディタで編集しHTMLコードを作成します。

さいごに

このたびの例題では360度を最高4つの領域に分割するにとどまっています。せっかくの矢印が期待した向きにならない場合は、chrome, opera, firefoxなどのブラウザをお使いください。デバッガはどのブラウザにも付属されています。デバッガの使い方については別の機会に譲りますが、右クリックし「検証」から進みます。