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-加群である。

PPAP(ペンパイナッポーアッポーペン)の代数的構造(2)

akiyah.hatenablog.com

の続きです。

左右の手

facebookで指摘を受けたのですが、歌詞の順番と右手と左手の順番は違うようです。歌詞に左右の手のどちらかを書いてみます。

PPAP

 

I have a pen (右手)
I have an apple (左手)
ah!
Apple pen!

 

I have a pen (左手)
I have a pineapple (右手)
ah!
Pineapple pen!

 

Apple pen (右手)
Pineapple pen (左手)
ah!
Pen-Pineapple-Apple-Pen!
Pen-Pineapple-Apple-Pen!

この左右の手を意識すると、前回とは違う式になります。右手は向かって左側、左手は向かって右側なので、演算の満たすべき条件を書いてみると、

ah!("✏", "🍎") = "🍎✏"

ah!("🍍", "✏") = "🍍✏" ←ここが変わる

ah!("🍎✏", "🍍✏") = "✏🍍🍎✏"

こんな風になります。なんとも一貫性がなくて困りますね。。。

ロングバージョン

2016/10/27 にロングバージョンというものが公開されていたようです。

www.youtube.com

ロングバージョンの中には今までにない演算結果も出てきています。 

 

ah!("✏", "✏") = "✏✏"

(ペンとペンでロングペンだそうです)

ah!("🍍", "🍎") = "🍎🍍" 

(アッポーとパイナッポーでアッポーパイナッポー)

ah!("✏✏", "🍎🍍") = "✏🍍🍎✏"

(ロングペンとアッポーパイナッポーでペンパイナッポーアッポーペン)

 

ここでロングペンは"✏✏"と表しています。ペンペンと呼びそうなものですが、呼び方だけはロングペンで実態はペンペンということにしておきます。

そしてもっと重要なことは、ペンがついていないときはアッポーが先の"🍎🍍"の順番だったのに、ペンがつくとアッポーがパイナッポーの後ろにいって"✏🍍🍎✏"になることです。どういうルールなのでしょう。もう少し考察してから答えを出します。

PPAP(ペンパイナッポーアッポーペン)の代数的構造

m.youtube.com

 

このエントリーではPPAP(ペンパイナッポーアッポーペン)の代数的な構造を明らかにする。

 

✏:ペン

🍎:アッポー

🍍:パイナッポー

 

として、これらのアイコンの有限列の集合をSとする。Sの元はわかりやすさのためにダブルクォーテーションで囲っておく。Sには例えば下記の様な元がある。

 

S ∋ "", "✏", "🍎", "🍍", "🍎✏", "🍍✏", "✏🍍🍎✏"

 

Sに演算 ah! : S✕S→S を定義する。

 

∀a, b∈S

ah!(a,b) := bを逆向きにした列にaをつなげた列

 

例えば以下のようになる。

ah!("✏", "🍎") = "🍎✏"

ah!("✏", "🍍") = "🍍✏"

ah!("🍎✏", "🍍✏") = "✏🍍🍎✏"

この演算でPPAPの歌詞における条件を満たしていることがわかる。

 

Sはこの演算でマグマである。単位元として""∈Sをもつ。結合則は満たさず、逆元も持たない。

 したがって、PPAPは単位的マグマである。

ヒートマップ比べ(データ:プリキュア視聴率、ツール:PowerBI)

久しぶりのヒートマップ比べシリーズです。今回はちょっと触ってみたPowerBIです。PowerBIは初めて触って1時間程度なので間違いがあるかもしれません。

さて、PowerBIでヒートマップを書いてみるか、と思ったけど、そういう視覚化はありませんでした。でもPower BI custom visualsというところでカスタムビジュアルというのが公開されていたので、Table Heatmapというカスタムビジュアルをインポートして試してみました。

PowerBIというよりTable Heatmapの制約なのでしょうけど、TableauRのときのようなRDBっぽいデータを入れるとヒートマップにできなかったので、Excelのときのような2次元の表のようなCSVファイルを作ってPowerBIに入れました。

あと、Excelで編集してShift-JISになっていたCSVファイルを入れると文字化けしたのでUTF-8に変更しました。

f:id:Akiyah:20161021101301p:plain

できた。一応。

やはりカスタムビジュアルの使いやすさの話なんだろうけど、縦横非が固定されているようで縦をもっと伸ばしたいのにできませんでした。色も変えられなさそう。

縦に並んだプリキュアシリーズの順番を変更できるようなUIになっているのですが、いまいち反映しなかったり。。。

PowerBIにとってはヒートマップは苦手分野だったということですかね。

それにしてもカスタムビジュアルというプラグイン形式のもので見た目を変えることができるというのは拡張性があっていいですね。

www.gixo.jp

こういうのとか。ちなみに今(?)はPower MapじゃなくてGlobeMapという名前になっているようです。