光る魔法陣、というのを作ったら娘と奥さんが喜んでくれた

 動かしてみると解ると思いますが、魔法陣っぽい図形がかけるツールです。Mahougenという魔法陣を作るAndroidアプリを私のAndroidタブレットに入れて娘に見せたら喜んでいたのだけど、娘が使っているデバイスはiPad miniなので入れられなくて、じゃあどこでも動くJavaScriptで作ってみようと思いました。 

kimihiro-n.appspot.com

このMahougenというアプリの線が書かれる動きがちょっとカクカクしていて気になったのもあって自分で作ったのです。が、上にある動画を見たらスムーズだったので私のタブレットが非力だったのかもしれないです。

作っているうちに、なんかエフェクトみたいなものがほしいなと感じて、光っているような風にしてみました。

娘に見せたら、「すげー」って言ってくれましたよ。よかった。奥さんもfacebookで友達にシェアしてて、それもうれしかった。

 

 

==追記(2016/12/16 10:52)== 

無いと書いちゃっていたけど、iOS版のMahougenあるようでした。作者の方、すみませんです。

kimihiro-n.appspot.com

 

three.jsのDragControlsはドラッグ中の動作が平面じゃなくて球面らしい

akiyah.hatenablog.com

に関連して。

three.jsDragControlsでのドラッグ&ドロップも上記のエントリーの様に、カメラからの視線と仮想的に作ったドラッグ用の平面を使って実現しているのだろうなあ、と思っていたら、実は違いました。球面のようですが、まだ正確にはソースコードを読み解いていません。

↓このアニメーションを見ると、後ろの方にあるオブジェクトが、ドラッグのたびに前に出てくるのが解ると思います。

 私としては、平面のほうが直感的でいいな、と思っています。DragControlsのパラメーターでドラッグ中の3D空間内の移動を選べたらいいのかな。

 

追記(2016/11/30 12:52)

局面だったのはバグだったらしい。devの最新で直っていました。処理もシンプルになっていて嬉しい。

DragControls: Simplified code using THREE.Plane approach. · mrdoob/three.js@50260c2 · GitHub

 

Three.jsのDragControlsとTrackballControlsと一緒に使ってドラッグ&ドロップをする

three.jsで遊んでいて、勉強のために書籍も買いました。 

three.jsによるHTML5 3Dグラフィックス〈上〉

three.jsによるHTML5 3Dグラフィックス〈上〉

 

購入した目的はドラッグ&ドロップを実現するDragControlsの使い方を知ることだったのですが、その目的は十分に達成できた良い本でした。2016年に出た改訂版です。改定前の本も買えちゃうと思うので注意してください。

で、DragControlsなのですが、ちょっと困った点があるのですよね。この書籍のp.280に書かれているのですが、DragControlsとTrackballControlsを組み合わせて使うと、TrackballControlsの動作中にDragControlsに処理を取られて思ったように動かなくなることがあります。

この書籍にはDragControlsやTrackballControlsのソースコードを変更するしか問題解決できない、と書いてあって、なかば諦めていたのですが、実際にやってみたらちょっとの工夫でまあまあ動作するようになりました。うれしかったのでこのエントリーを書いています。

jsdo.it

↑ここにソースコードは書いていますが、DragControlsのdragstart, dragendイベントでTrackballControlsの有効無効を切り替えれば良いようです。

var dragcontrols = new THREE.DragControls(camera, objects, renderer.domElement);
dragcontrols.enabled = true;

dragcontrols.on('dragstart', function(e) { controls.enabled = false; });
dragcontrols.on('dragend', function(e) { controls.enabled = true; });

こんなふうに。もしかしたらthree.jsがバージョンアップして、書籍執筆時にはできなかったことができるようになったのかもしれません。

3D物理エンジンと3D描画ライブラリでドラッグ&ドロップをするやり方

f:id:Akiyah:20161117020436p:plain

3D物理エンジンテンセグリティのシミュレーションをしようと思って、Cannon.jsとかOimo.jsを触ってみているところです。ちょっと触ったCannon.jsではテンセグリティの張力(バネ)の使い方がややこしかったので、いまはOimo.js実験しています。

3D物理エンジンでのテンセグリティのシミュレーションは、棒の長さとか、張力の強さとかを簡単に変更して試したいという動機なんですが、できれば触っている感触を得たいじゃないですか。というわけでマウスでのドラッグ&ドロップをやってみようと思いました。

3次元の物体を2次元の画面上のマウスポインターでドラッグ&ドロップする方法を探して、Cannon.jsちょうどいいサンプルがありましたのでそれを参考にします。考え方の話なので特定の3D物理エンジンと3D描画ライブラリには依存しませんが、ここではOimo.jsthree.jsを想定して書きますね。あと、3D物理エンジンと3D描画ライブラリの両方をうまく組み合わせてドラッグ&ドロップを実現するので、なかなかややこしいです。一言で言えば、3D空間内にドラッグ用の平面を作って、そこでスプリングを使ってドラッグ&ドロップする、ですね。

↑ドラッグした直後にオブジェクトがずれることがあるので、なにか計算ミスしている気がします。。。

 

【登場オブジェクト】

3D物理エンジン

  • ドラッグ&ドロップされる対象のオブジェクト
  • ドラッグ用の点
  • ドラッグ用のスプリング

3D描画ライブラリ側

  • カメラ
  • ドラッグ用の平面

その他

  • マウス

 

【ドラッグ&ドロップの流れ】

(1) マウスのボタンを押す

(1-1) カメラから見たマウスのポインターを3D空間上の直線に変換する

three.jsだとこんな感じです。

var ray = new THREE.Raycaster();

ray.setFromCamera(mouse, camera); 

(1-2) その直線と「ドラッグ&ドロップされる対象のオブジェクト」の一番手前で交差する点を見つけて、ドラッグオブジェクトとドラッグポイントを使えるようにする。

three.jsだとこんな感じです。

var intersects = ray.intersectObjects(views, true);

if (0 < intersects.length) {

    dragPoint = intersects[0].point;
    dragBlockName = intersects[0].object.name;

    ....

}

(1-3) そのドラッグオブジェクトとドラッグポイントを使って、「ドラッグ用の点」「ドラッグ用のスプリング」「ドラッグ用の平面」を配置する。

「ドラッグ用の点」は、ドラッグポイントに置きます。

「ドラッグ用のスプリング」は、「ドラッグ用の点」とドラッグオブジェクトのドラッグポイントを結ぶようにします。最初は始点と終点は同一の点です。

「ドラッグ用の平面」は、ドラッグポイントを中心としてカメラの視線に対して直行するように置きます。「ドラッグ用の平面」は画面上に表示する必要は無いのですが、開発中は見えているとわかりやすいので表示しておいたりします。下の画像のようになります(この画像ではドラッグ後にマウスがすこし動いたあとです)。

f:id:Akiyah:20161117020439p:plain

(2) マウスを移動する

(2-1) カメラから見たマウスのポインターを3D空間上の直線に変換する

これは(1-1)と同じです。

(2-2) その直線と「ドラッグ用の平面」の一番手前で交差する点を見つけて、ドラッグポイントを使えるようにする。

これは(1-2)と似ていますが、対象が「ドラッグ用の平面」になっています。

(2-3) そのドラッグポイントを使って、「ドラッグ用の点」「ドラッグ用の平面」を移動する。

「ドラッグ用の平面」を使って2次元の範囲で移動させるのがコツです。「ドラッグ用のスプリング」は始点と終点が離れていきます。それによって、ドラッグポイント(マウスの位置)にドラッグオブジェクトが引っ張られます。

(3) マウスのボタンを離す

(3-1) 「ドラッグ用の点」「ドラッグ用のスプリング」「ドラッグ用の平面」を消す。

これで一回のドラッグ&ドロップは終わりです。マウスのボタンを離す以外にも、マウスポインターがウィンドウから出た場合もドロップしたとみなしても良いかもしれません。

 

どうでしょうか。結構ややこしいですね。ドラッグ用のスプリングは3D物理エンジンの世界にあって、カメラやドラッグ用の平面は3D描画ライブラリの世界にあるので、どちらかのライブラリにプラグインを入れて解決、というわけにも行かないのが辛いところです。

私は3D物理エンジンに詳しいというわけではないので、もっと簡単にできるいいドラッグ&ドロップがあるのかもしれません。

Cannon.jsサンプルに比べて、私が作ったものはキビキビしていないのがちょっと悔しいところです。改善予定です。そしてドラッグ&ドロップを使って3D空間内でテンセグリティをシミュレーションができるようにしたいです。

老年人口割合の推移を都道府県別で出してみた

前回の交通事故統計のpdfを見てて、沖縄県の老年人口割合がダントツで低かったので、その推移が気になって調べてみました。

最初に見たのはRESASの人口ピラミッドなのですが、これだけだと2つの集計年に対しての比較はわかりやすいけど、推移のグラフではありませんでした。

f:id:Akiyah:20161104014458p:plain

でも右下に「データをダウンロード」というボタンがあって、ダウンロードしてみたら都道府県別で集計年別の老年人口割合があったので、それを使いました。ちなみに割合は丸められていたので、改めて表計算ソフトで老年人口を人口で割って計算して出しました。そのあとピボットテーブルを作って集計して、そして折れ線グラフにしました。(TableauやExploratoryを使ったほうが良かったのかも)

f:id:Akiyah:20161104014725p:plain

全体として、老年人口の割合がグイグイ増えていますね。こういうデータは何度も見たけど、あらためて高年齢化が進んでいるのがわかります。

さて、2010年から沖縄県がひとつだけ老年人口割合が飛び抜けて低くなっています。なぜなんでしょうね。不思議です。何年からこの傾向があるのか、5年毎ではなくて1年毎のデータを見たいところです(またいずれ)。

ちなみに、2015年の沖縄の次に老年人口割合が低いのは東京都です。

警察庁の交通事故統計で年齢層別死者数の推移を見てみた→高齢者の死亡率↓

www.jiji.com

この記事を読んで、65歳以上の交通事故死者数が横ばいだけど、高齢者の人数は増えているので死亡率はどういう推移をしているのか気になったので調べてみました。

統計|警察庁からe-Statの交通事故統計(平成28年9月末)Excelファイルのシートの3と4を見ました。とりあえず上記の記事よりも年代の区切り方が細かいので、それをグラフにしてみました。

f:id:Akiyah:20161103023358p:plainf:id:Akiyah:20161103023816p:plain

合計の人数が最初の記事と違いますが、もしかして集計の方法が違うのかもしれません。(ちょっと気になりますが先に進みます)

人数だけ見ると、どの層も減少傾向ではありますが、高齢者層の減少率は低そうです。

次に10万人当たりの死者数の推移を見てみましょう。

f:id:Akiyah:20161103023359p:plain

おっと、こうしてみると、高齢者層の死亡率が確実に減っていますね。これは発見でした。人数のグラフで死亡者数があまり減少していなかったのは、高齢者の人数が増えていたからでしょうね。

なにが影響して交通事故の死者率が減っているのか私にはまだわかっていないのですが、この減少傾向は素晴らしいし、まだ減ってくれそうですね。

もしかして自動運転などが実現すればもっと安全な世界が実現されるのかもしれません。期待です。

e-Statのデータはニュースの記事よりも細かくて助かります。もっと扱いやすくなってくれたらなお嬉しいです。

PPAP(ペンパイナッポーアッポーペン)の代数的構造(3) PPAPはランク3の自由Z-加群

1回目の記事でPPAPは単位的マグマと書いたけど、2回目の記事でそれでは説明できないサンプルがあって、否定されてしまいました。

というわけで、演算を最初から作りなおして整合性がある状態にします。

いきなりですが✏(ペン)、🍎(アッポー)、🍍(パイナッポー)の3つの文字に対して、

S := { n✏ + m🍍 + l🍎 | n, m, l ∈ 整数Z }

とします。つまりSは集合{✏, 🍎, 🍍}を基底として持つ自由Z-加群である。Sの元としては、

1✏ + 1🍍 + 2🍎

-2✏ + -3🍍 + -5🍎

0✏ + 1🍍 + 0🍎

0✏ + 0🍍 + 0🍎

こんなものがあります。このままだと表現しにくいので、1や+は省略して、0がかかっている文字も省略します。

1✏ + 1🍍 + 2🍎 → ✏🍍2🍎

-2✏ + -3🍍 + -5🍎 → -2✏-3🍍-5🍎

0✏ + 1🍍 + 0🍎 → 🍍

0✏ + 0🍍 + 0🍎 → 0

マイナスがつくとちょっと見た目がアヤシイですが、まあ気にしないでください。

演算の条件を満たすように、特別なときだけ見た目を変更するようにします。

 

ペン✏は、係数が1より大きい時はひとつだけ右側に書きます。

✏🍍🍎 → ✏🍍🍎 (変わらず)

2✏🍍🍎 → ✏🍍🍎✏

3✏🍍🍎 → 2✏🍍🍎✏

 

アッポー🍎とパイナッポー🍍は、それぞれの係数が1でペン✏の係数が0の時だけ、逆順にします。

✏🍍🍎 → ✏🍍🍎 (変わらず)

🍍🍎 → 🍎🍍

 

この見た目に関するルールを入れると、満たすべき条件が全て成立するのです。

✏ + 🍎 = 🍎✏

✏ + 🍍 = 🍍✏

🍎✏ + 🍍✏ = ✏🍍🍎✏

✏ + ✏ = ✏✏

🍍 + 🍎 = 🍎🍍

✏✏ + 🍎🍍 = ✏🍍🍎✏

 

というわけで、PPAPはランク3の自由Z-加群である。