Scala 関西ビギナーズに参加した

2012/12/22 に Scala関西ビギナーズ 第1回 が開かれた。「みんなで Scala やろうぜ」という勉強会だ。

僕の中では最近関数型言語の興味が高まっていて、実際にバシバシ書いてみたいと思っていた。そんなときにこの勉強会のことを知って、Scala で課題を解く時間もあるみたいで丁度いいと思って参加することにした。

内容

まずは前半は @aa7th さん、 @mumoshu さんの発表。

@aa7th さんの発表は、Scala の概要とか長所短所など基本のお勉強。ScalaJVM で動作するプログラム言語です、とかふむふむ聞いてた。

と思いきや途中からコードゴルフに。

こんなダサいコードが、

val start = args(0).toInt
val end = args(1).toInt

var sum = 0
for (num <- start to end)
  sum += num

println(sum)

Scala ならこんなにおしゃれになります!

println((0 /: (args(0).toInt to args(1).toInt)) (_+_))

Scala すげー!

まあ別に短ければそれで良いって訳でもないし、記号が多くて正直やり過ぎの感はあるけど、でも短くする過程でさり気なく var (再代入可能な変数) が無くなってるってのがポイント。Scala はこうやって自然に関数型言語のメリットを受けられる言語だと思う。

というわけで、今回学んだ Scala の特徴は以下。

  • 手続き型言語のようにもかける
  • 関数型言語のようにもかける
  • 冗長な記述が不要
  • しかし型のチェックなど静的型付けの特徴は失われていない

書きやすくて、それでいて安全な言語という事で、やっぱり Scala 便利。

発表資料は slideshare で公開されてるので復習しておこう。

課題

前半でいい感じに盛り上がったところで、いよいよ後半の課題の時間。Project Euler の問題Scala で解いていった。

1問目はけっこう簡単な感じで「こりゃ楽勝、ばんばん解くぜ」とか思ってたけど、2問目からいきなり難しくなった。ごり押し計算では終わらなさそうなやつとかにくじけそうになりつつも、なんとか problem 1と4を解答した。

問題数としてはあんまり進まなかったけど、色々考えながらコーディングできたし、困った時に教えてくれる先生もいて、ほんとに勉強になった。

感想

Scala はやってる人が少ないとかとっつきにくいとか言われてるみたいだけど、こういうイベントがあると勉強するきっかけになるし、全体としても盛り上がると思う。今回の勉強会は良いきっかけになりました。開催してくれた @aa7th さん、ありがとうございました!

あとは、この手の勉強会は予習復習が大事だと思う。僕の目標はこんな感じ。

  • コップ本を読む
  • 何か Web サービスを作る

がんばる。

あと、今回の会場のオオサカンスペースは駅から近いし、おやつもあるし、楽しそう。普段の勉強の時とかにも使ってみたくなった。こっちにも注目。

第2回 関数型言語勉強会 大阪に参加した

2012/11/24 に、第2回 関数型言語勉強会 大阪が開かれた。 なんかすごい人気で補欠だったんだけど、ぎりぎり参加できた。 勢いでLTしてきたので公開する。

JavaScript関数型言語

関数型言語は人気ないけど、JavaScript はみんな使ってるし関数型言語っぽく使えるし、JavaScript関数型言語はやらせたら良いと思って発表した。

関数型言語っぽい JavaScript の使い方はこんな感じ。

filter

filter はリストの中から条件を満たすものだけを集める処理のこと。

Haskellで書くと ...

-- 0より大きいものだけ集める
xs = [-2, -1, 0, 1, 2]
filter (\x -> x > 0) xs
-- => [1, 2]

関数型言語っぽい。

伝統的なJavaScriptの場合

var xs = [-2, -1, 0, 1, 2];
var result = [];
for (var i = 0; i < xs.length; i++) {
  if (xs[i] > 0) {
    result.push(xs[i]);
  }
}

// => result は [1, 2]

かっこわるい。いまどき for のループとか意味が分からない。

でも、最近のJavaScriptならちゃんと書ける。

var xs = [-2, -1, 0, 1, 2];
var odd = xs.filter(
  function(x) { return x > 0}
);

// => [1, 2]

おしゃれ!

これは ECMAScript 5の仕様に追加されている。 対応していないブラウザは無視してよい。 ばんばん使っていきましょう。

map

map はリストのすべての要素に関数を適応して新しいリストを作るやつ。

Haskellで書くと ...

-- 全部2乗する
xs = [1, 2, 3, 4]
map (\x -> x * x) xs
-- => [1, 4, 9, 16]

いいね、いいね。うらやましい。

JavaScriptでもできる。

var xs = [1, 2, 3, 4];
var square = xs.map(
  function(x) { return x * x }
);
// => [1, 4, 9, 16]

reduce (たたみこみ)

reduce はリストを順に処理して一つにまとめるやつ。

Haskellで書くと ...

-- 1から4まで足し算する
foldl (+) 1 [2, 3, 4]
-- 10

当然JavaScriptでもできる。

var xs = [1, 2, 3, 4];
var sum = xs.reduce(
  function(x, y) { return x + y }
);
// => 10

reduceRight を使うと右から結合できる。

部分適応

部分適応は、元の関数から引数の一部を固定した新しい関数を作ること。

Haskellで書くと ...

-- かけ算する関数があります
product x y = x * y

-- 片方を-1で固定
neg = product (-1)

neg 5
-- => -5 (-1 * 5 を計算している)

JavaScriptでもできます!

var product = function(x, y) { return x * y };

// product の第1引数が -1 に固定された関数を作る
var neg = product.bind(null, -1);

neg(5) // => -5

応用例

こういうやりかたを使うと、例えば平均と標準偏差を求める計算はこんな感じで書ける。

var calc = {
  "+" : function (x, y) { return x + y },
  "-" : function (x, y) { return x - y },
  "*" : function (x, y) { return x * y },
  "/" : function (x, y) { return x / y },
  "^" : function (exponent, base) { return Math.pow(base, exponent) }
};

// 符号を反転
calc["neg"] = calc["*"].bind(null, -1);
// 2乗
calc["^2"] = calc["^"].bind(null, 2);
// ルート
calc["^(1/2)"] = calc["^"].bind(null, 0.5);


// 平均を計算する
var getMean = function(array) {
  return calc["/"](array.reduce(calc["+"]), array.length);
};
getMean([1, 1, 3, 5])
// => 2.5

// 標準偏差を計算する
var getStddev = function(array) {
  var mean = getMean(array);

  return calc["^(1/2)"](
            calc["/"](
                array
                  .map(calc["+"].bind(null, calc.neg(mean)))
                  .map(calc["^2"])
                  .reduce(calc["+"])
                ,
                calc["-"](array.length, 1)
         )
  );
};

getStddev([1, 1, 3, 5]);
// 1.9148542155126762

感想

関数型言語なんて誰も使っていない空想の言語と思ってたけど、参加者がかなり多くて驚いた。 特に実際のサービスで使っている人の話が聞けて、とてもありがたかった。 なんかもう関数型言語ってそんなに特別なものではなくて、普通に選択肢に入るような感じ。

勉強会に参加して気合が高まって何でもできそうな感じなので、僕も何かサービス作ってみようと思う。 こうやってやる気が高まったので参加してよかった。

「伝わるプレゼン」という発表をしてきた

5/8に「プレゼン勉強会」というイベントがあった。
【大阪開催】5月8日にプレゼン勉強会を開催します! - 頭ん中
プレゼンするときに気をつけていることなんかを発表して共有する勉強会のようだ。

僕はこの前『俺の話を聞け!2012』 でプレゼンについて発表したんだけど、それがきっかけで今回もお話ししてみませんか、みたいな感じで招待された。

平日でちょっと参加しにくかったけど、せっかくなので前回の内容を元に手を加えて発表することにした。

しかし、勉強会のテーマがプレゼンということでかなりハードルが高い。どうなることやら、と不安を抱えつつ参加した。

発表内容

発表のタイトルは「伝わるプレゼン」。

プレゼンをするときの「テーマ選定」「資料作成」「当日の発表」と大きく3つに分けてお話しした。その中でも僕は「資料作成」が簡単で効果的だと思うので、そこをポイントとしてお話ししてきた。

スライドの中でも書いたけどPresentation Patternsというサイトとかに良さそうな手法がまとまっていているので参考にしてみるといいと思う。

今回他の方の発表なんかでもいろいろ注意点が出てきたけど、僕は基本的に出来ないことはあきらめて、出来る範囲のことをがんばるようにしてる。

なぜかというと、発表の評価って加点評価だから。ちょっとぐらい欠点があっても、聴いている人に役に立つとか注目のポイントがあればきっとプラスの評価になると思う。なので出来ないことは気にせず好きなこと、得意なことをがんがんアピールしていけばいいと思う。

ただし、最近は自分なりのパターンが固定されてきて、発表するスタイルとかやっていることが狭くなっているように感じてる。なので他の人とかを参考にしてもうちょっと、今までやったことがないことにも挑戦していきたい。

イベント全体について

今回はテーマがプレゼント言うことで、営業の人とか技術系でない方も参加されていた。誰にでも関わりのある内容で幅広い方が参加されて、プレゼンの考え方を共有するというイベントの趣旨がうまく達成できたと思う。

僕は勉強会を主催したり人を集めたりとかはあんまり得意でないので、今回主催者の@msngさんのようにイベントを開いてくれる方は本当にありがたいと思っています。そんな方に「勉強会を開くので発表しませんか」と声をかけてもらってとても光栄です。

次は6月2日に『俺聞け3』が開かれるようだ。こっちにも参加しようと思う。

「伝わるプレゼンをする方法」という発表をしてきた

3/3に「俺の話を聞け」というイベントがあった。
『俺の話を聞け!2012』を開催します - 頭ん中

何を話してもOKな自由な勉強会のようだ。良い機会なので、勉強会で発表するときのコツ、気をつけることについて自分なりにまとめてみて発表することにした。最近ほとんど勉強会とか出ていなくて久しぶりの発表なので、けっこう緊張しながら会場に向かった。

発表内容

発表のタイトルは「伝わるプレゼンをする方法」。

僕が普段から発表するときに気をつけていること、ということで「ストーリーを付けると良いよ」という内容で話してきた。

スライドには書けなかったこともあるのでちょっと補足する。

  • 前半は誰にでも分かる人目を引く話をして聞き手を引きつけると良い。いわゆる「つかみ」。
  • 「これを聞いてくれ!」「これがすごい!」と気持ちを込めて伝えると盛り上がる
  • 発表中は失敗しても気にしない。失敗してしまったものはどうしようもないし、フォローしようとしてもたいてい逆効果になるだけ。反省会は家に帰ってからやる。
  • 発表資料を作るときは、画面の上下、左右の端まで書かないようにする。スクリーンが切れて見えなくなることがあるから。特に下の方は後ろの人からは見えにくいので注意する。
  • 他の人の発表を見るのが一番参考になる。うまいと思ったところは真似して、良くないと思ったところはそうならないように注意する。

後はスライドの中でも書いたけど、Presentation Patternsというサイトにいい感じの手法がまとまっていている。こういうのを参考にしながら自分なりのやり方を見つけていくのが良いと思う。

でもここに挙げたのは発表の手法であって、そもそも内容が一番大事ということは忘れないようにしよう。

イベント全体について

久しぶりに勉強会に参加して色々刺激になった。やっぱりがんがんアウトプットするのが大事だと思う。発表するのは準備とか大変だしはっきり言って面倒くさいけど、聞いてくれる人がいればこそできることだと思う。主催者の@msngさん、参加者の皆さん、ありがとうございました。

最近あまり目立つ活動をしていなくてちょっと世間の流行から取り残されていたような感じだったので、これをきっかけにいろんなイベントに参加して活動を復活しようと思う。

あと、次は zsh で発表したい。

Node.jsとnvmを初めてインストールするときのハマりポイントと対策

最近何かと話題の Node.js を使ってみることにした。 インストール自体は公式の Wiki を見ればそんなに難しくない。いつもの configure, make, make install するだけだ。

でも Node.js はまだまだ開発中のプロジェクトで、今でもがんがん更新されてる。すぐに新しいバージョンが出てくるんだけど、そのたびにソースからインストールし直すのもいやだし、ちょっと前のバージョンに戻したくなることもあるかもしれない。

そんなわけで、最近の Node.js は nvm というツールを使うのが流行みたいだ。こいつを使うと複数バージョンのインストール、切り替えが出来るようなって便利。

Mac でも Linux(Ubuntu) でも使えるんだけど、微妙にハマったとこがあったので手順を書いておく。

2012/03/21追記

npm でのパッケージのインストール、設定について追記した。

準備

まず始めに、必要なパッケージとかをあらかじめインストールしておく。

Ubuntu の場合

Node.js をビルドできるようにするために、以下をインストールする。

% sudo aptitude install build-essential
% sudo aptitude install libssl-dev

あと、nvm は wgetcurl の両方が必要になる(統一しろよ...)。Ubuntu はデフォルトで curl が入っていないのでインストールしておこう。

% sudo aptitude install curl
Mac の場合

Mac でも基本的に Ubuntu と同じ。まず XCode をインストールして Node.js 自体をビルドできるようにしよう。

Mac の場合、 curl は入ってるんだけど wget が入っていないのでインストールする。

# homebrew を使う場合
% brew install wget

# Mac ports を使う場合
% sudo port install wget

もちろんインストール済みならそのままで OK。この辺は各自の環境に合わせて適当に調整しよう。

nvm のインストール

nvm は Node Version Manager のことで、Node.js のインストール、バージョンごとの管理、シェルの環境設定をやってくれる。

nvm を使うには Github のリポジトリをクローンする。

% git clone git://github.com/creationix/nvm.git ~/.nvm

あとは nvm 本体を source すれば OK。

% source ~/.nvm/nvm.sh
2012/03/20追記

以前は zsh でエラーが出ていたけど、現状の最新バージョンでは修正されてるので以下の対応は不要になった。念のため以前の対応内容も残しておく。

旧バージョンでエラーが出ていたときの対応(現在は不要)

... のはずなんだけど zsh の場合はエラーが出てしまう。実は nvm.sh は bash が前提になっていて、${BASH_ARGV[0]} ってとこが zsh で解釈できないからだ。

この問題は本家の Issues にも挙がってるので、それを参考に bash でも zsh でも動くように直した。

diff --git a/nvm.sh b/nvm.sh
index 99eb87a..9e9951b 100644
--- a/nvm.sh
+++ b/nvm.sh
@@ -5,8 +5,7 @@
 # Implemented by Tim Caswell <tim@creationix.com>
 # with much bash help from Matthew Ranney

-# Auto detect the NVM_DIR using magic bash 3.x stuff
-export NVM_DIR=$(dirname ${BASH_ARGV[0]})
+export NVM_DIR=$(cd $(dirname ${BASH_SOURCE[0]:-$0}); pwd)

 nvm()
 {

これを適応して、改めて source してみよう。

% source ~/.nvm/nvm.sh

エラーが出なくなった。よしよし。

nvm を使用して Node.js をインストールする

いよいよ Node.js 本体をインストールする。nvm がちゃんと入っていればコマンド1つ打つだけでよくて簡単。

今回は 0.4.0 をインストールした。

% nvm install v0.4.0

インストールできたら use コマンドを使って環境を切り替える。

% nvm use v0.4.0
Now using node v0.4.0

ちゃんとインストールできてるか確認してみよう。

% node --version
v0.4.0

OKOK。パスも通ってる。

別のバージョンもインストールできる。試しに0.3系もインストールしてみた。

% nvm install v0.3.8

複数インストールした後は nvm ls コマンドでバージョン一覧が見れる。

% nvm ls
v0.3.8
v0.4.0 *

今有効になってるバージョンには * がつく。別のバージョンに切り替えたいときは use コマンドを使おう。

% nvm use v0.3.8
Now using node v0.3.8

% node --version
v0.3.8

これで複数のバージョンを切り替えできるようになったし、新しいバージョンが出ても簡単に更新できる。

インストールできるバージョン一覧は nvm コマンドでは見れないので、公式のダウンロードページで確認しよう。

npm でモジュールをインストールする

Node.jsでは npm を使って追加のパッケージを管理する。nvm を使うと npm も使えるようになっているので早速試してみる。
バージョンは node v0.6.9, npm 1.1.0-3 で確認した。

# formidable パッケージをインストール
% npm install -g formidable

-g オプションを付けるとグローバルインストールになって、Node.js がインストールされている共通の領域にパッケージがインストールされる。nvm を使用している環境の場合、バージョン別の場所にパッケージがインストールされる形になる。
例えば nvm use v0.6.9 をした後は ~/.nvm/v0.6.9/lib/node_modules の下にインストールされる。

ただし、こうやってインストールしたパッケージを使おうと node を起動しても「見つかりません」というエラーが出てしまう。

これを防ぐために NODE_PATH 環境変数を指定する。node 本体は NODE_PATH からパッケージを探してくれるので、パッケージをインストールしたディレクトリを指定しておけばうまく動く。

# nvm use した後に以下を実行
% export NODE_PATH=${NVM_PATH}_modules

シェルの設定を追加

nvm の設定はログアウトすると無くなってしまうので、シェルの初期化ファイルに書いておこう。

# ~/.zshenv, ~/.bash_profile などに以下を追加
source ~/.nvm/nvm.sh
nvm use "v0.4.0"

ただし、この書き方の場合 nvm とかがインストールされてない環境で余計なエラーが出てしまう。それではかっこわるいのでインストール済みかどうかチェックするようにした。

# nvm と指定されたバージョンの Node.js がインストール済みの場合だけ
# 設定を有効にする
if [[ -f ~/.nvm/nvm.sh ]]; then
  source ~/.nvm/nvm.sh

  if which nvm >/dev/null 2>&1 ;then
    _nodejs_use_version="v0.4.0"
    if nvm ls | grep -F -e "${_nodejs_use_version}" >/dev/null 2>&1 ;then
      nvm use "${_nodejs_use_version}" >/dev/null
      export NODE_PATH=${NVM_PATH}_modules${NODE_PATH:+:}${NODE_PATH}
    fi
    unset _nodejs_use_version
  fi
fi

インストール済みの場合だけ nvm use するようにした。.zshrc をいろんな環境で使い回してるときはこうした方がいいと思う。

これでインストールと環境設定は終わり。新しいバージョンが出てきても簡単に設定を変えれるようになったし、もう安心だ。

15分でわかる zsh

2011年01月29日(土) に大阪で Minami.rb 第4回勉強会 が開かれた(告知ページ)。Ruby on Rails(Ruby)メインの勉強会だ。

そこで15分枠の発表コーナーがあったので zsh の発表をしてきた。zsh って高機能なんだけど、実はシェルに詳しくない人でも便利に使える。なので、なんか興味あるけど難しそうって思ってる人は参考にして欲しい。

発表資料

発表資料はこんな感じ。これ自体はあんまり読まなくてもいいけど、一応貼り付けておく。

これに実際のコマンドライン操作を見せながら説明した。発表内容は以下。

補完

zsh はなんと言っても補完が便利。とにかくこれを ~/.zshrc に書いておこう。

autoload -Uz compinit
compinit

これでいろんなコマンドのオプション、引数をかしこく補完できるようになる。

grep の補完の例

例えば grep の場合。オプションを指定するとき普通はこんな感じになると思う。

% grep -nH -r 'method1' src

でも -n とか -H とか覚えてられない。毎回 --help とか man とかで調べてる人もいるかもしれない。

1文字のオプションは分かりにくいってことで、長いオプションも用意されてる。

% grep --with-filename --line-number --recursive 'method1' src

これはこれでめんどくさい。--with-filename なんて打ってたら日が暮れる。

zsh の補完を使うとこれが全部解決できる。

% grep --wi[TAB]        # ここでタブを押す
% grep --with-filename  # オプション名が補完される
% grep --with-filename --line[TAB]     # 今度もタブを押す
                                       # 候補が出てくる
  --line-buffered        -- flush output on every line
  --line-number          -- prefix output with line numbers
  --line-regexp          -- force pattern to match only whole lines

% grep --with-filename --line-number   # 何回かタブを押して欲しいものを選ぶ

ポイントはオプション名が分からなくてもいいってとこ。何となく名前を入れて、後は補完して選べば OK。オプション名を覚えたり入力したり、そんなどうでもいいことにパワーを使う必要はない。

git の補完の例

みんな大好きな git も当然補完できる

% git a[TAB]     # git コマンドの補完
% git add -[TAB] # add のオプションの補完

% git add [TAB]  # add するファイル名の補完
                 # 編集済みのファイルしか出てこないので、
                 # add する必要のあるファイルだけが補完される

checkout の場合もいい感じに補完してくれる。

% git checkout [TAB] # ファイル名とブランチ名を補完

ブランチを行ったり来たりするときに便利。

その他補完が便利になるもの

その他、補完が便利になるものとしてこんなものがある。

  • man
  • cd
  • kill
  • apt-get

使い方も同じで、何か欲しくなったときにタブを押すだけ。それだけで man の場合はマニュアルページ名を補完してくれるし、 cd の場合はディレクトリ名だけが補完できる。

もちろんこれ以外でも、よく使うコマンドはたいてい対応している。

とにかくこの機能が便利。適当にタブを押すだけでいい感じのものが補完されるので、自分で考えて入力するってのが激減する。

ファイル名生成

補完以外にも、** で指定する再帰的なファイル名生成が便利。

% grep h1 **/*.html

これは grep h1 *.html */*.html */*/*.html ... という意味になるので、今のディレクトリ以下の html ファイル全部が grep 対象になる。

いろいろ使い道がある。

% rm -f **/*.bak  # .bak を削除する
% vim **/*.rb     # ruby ファイルを vim で開く

ファイルを探すのにも使える。

% ls **/MyClass.rb  # ファイル名を指定して探す
% ls **/*.png       # png ファイルを探す

「あのファイルどこいったのかなー」ってときに便利。find コマンドでも同じようなことが出来るんだけど、それよりも簡単に使えてうれしい。

まとめ

なんと言っても zsh は補完が便利。しかも使い方はタブを押すだけ。それだけで zsh がそのとき必要なものを出してくれる。

なので、コマンドラインの操作になれてない人でも便利に使える。というか、コマンドとかオプションとか全部覚えてたら補完する必要はないわけで、あんまりなれてない人にこそ使って欲しい。

zsh は高機能なので難しい設定とかしてる人もいるけど、初心者でも役に立つので自分の扱える範囲で活用して欲しい。

.zshrc の例

簡単な .zshrc の例は以下。とりあえず最初はこのあたりから始めてみよう。

# 強力な補完を有効にする
autoload -Uz compinit
compinit

# ヒストリの設定
HISTFILE=~/.zsh_history
HISTSIZE=10000
SAVEHIST=10000

# emacs 風キーバインドにする
bindkey -e

# その他とりあえずいるもの
export LANG=ja_JP.UTF-8
setopt print_eight_bit   # 日本語ファイル名を表示可能にする
setopt no_flow_control   # フローコントロールを無効にする

参考資料

漢のzsh | マイコミジャーナル
マイコミジャーナルの連載記事。ちょっと古いけど今読んでも役に立つし、 zsh の一通りのことが解説してある。
連載:zshで究極のオペレーションを|gihyo.jp … 技術評論社
zsh の本の著者による連載記事。
zsh 記事一覧 - ess sup
僕のブログの zsh 記事一覧。
.zshrc - GitHub
僕の .zshrc ファイル。GitHub で公開してる。

Kanasan.JS JavaScript第5版読書会でベジエ曲線について発表した

2011年01月15日(土) に京都で Kanasan.JS JavaScript第5版読書会 #11 が開かれた(告知ページ)。みんなでサイ本を読む会だ。第1回からだいたい3年ぐらい続いてて、今回でいよいよ最終回となった。僕は途中半分の第6回くらいからの参加なんだけど、最後のまとめとして気合いを入れて参加した。

読んだところ

今回は P561 から P629(最後)まで。主にクライアントサイドのグラフィック制御のところを読んだ。

いろんなグラフィック関係のテクニックが書いてあったけど、本が出てから時間がたってることもあって今では使わないようなものもあった。その中で注目はやっぱり SVGcanvas 要素。サンプルコードが書いてあったのでみんなで読んだ。

SVG

SVGXML で定義された画像フォーマットの一種。V は Vector の V で、その名の通りベクターグラフィックになってる。HTML の中に SVG を埋め込めて、さらにそいつを JavaScript から操作できる。

指定した経路に沿って線を書くこともできる。例えば扇形を書くときはこんな風に経路を指定する。

// この文字列に線の経路情報を保持する
var d = "M " + cx + "," + cy +    // 始点(円の中心)
        " L " + x1 + "," + y1 +   // 始点から (x1, y1)まで直線を引く
        " A " + r + "," + r +     // 円弧の半径
        " O " + big + " 1 " +     // 円弧の向き。
                                  // 終端まで弧を書く際に近いほう/遠いほうのどちらを通るかを指定する
        x2 + "," + y2 +           // 円弧の終端
        " Z";                     // 始点まで戻って終わり

超読みにくい。でもこんな指定を繰り返すと円グラフが描けたりする。

canvas 要素

canvas 要素は JavaScript で動的に画像を描くための要素。できあがりはビットマップ画像になる。lineTo, arc などの API を使ってチマチマ画像を描いていく。その後僕は発表したんだけど、そこでも canvas を使った。

ベジエ曲線について

今回はグラフィック関連の章ということで、僕はベジエ曲線について発表した。

ベジエ曲線って名前は聞いたことある、もしくは使ったことあるっていう人も多いんじゃないのかな。 Illustrator, Photoshop とかでも描けるし、canvas 要素の quadraticCurveTo(2次)、bezierCurveTo(3次)という API でも描ける。

でもアルゴリズムまでは知ってる人少ないと思う。僕は学校でそういうの勉強したので、いい機会だと思って発表した。

ベジエ曲線とは

ベジエ曲線とは、線分の内分点を取る操作を繰り返すことにより得られる曲線のこと。といってもよく意味が分からないかもしれない。jsdo.it でデモページを作ったので適当に遊んで欲しい。

入力となるいくつかの点があって、そこからアルゴリズムに基づいて曲線を描く。その「いくつかの点」というのを制御点という。Illustrator では「開始地点のアンカーポイント」とか呼ばれてるやつね。

数学的な理論の話は「ベジエ曲線とベジエ曲面」というページに書いてある。大学の講義用の資料でかなり本格的。その中で、曲線の定義、表現方法は「ベジエ曲線とベジエ曲面1」と「ベジエ曲線とベジエ曲面2」を読むと分かる(どっちも PDF ファイル)。

JavaScript での実装

僕のデモページで一番大事な関数は以下。ベジエ曲線上の1点を求めてる。

// bezierCurve.js 58行目

// 与えられた制御点に対して、 t を固定して得られる
// ベジエ曲線上の1つの点を取得する
// @points : 任意の数の制御点を格納した配列
bezierPointT : function(t, points) {
    if (points.length >= 2) {
        var dividedPoints = [];
        for (var i = 0; i < points.length - 1; i++) {
            dividedPoints.push(
                BezierCurve.dividePoint(t, points[i], points[i+1]));
        }
        return BezierCurve.bezierPointT(t, dividedPoints);
    } else {
        return points[0];
    }
}

この t を0から1まで動かせばなめらかな曲線になる。実際には連続的に無限の点を求めることはできないので、0から1までを適当に分割して折れ線で近似してる。

拡大/縮小、平行移動

ベジエ曲線の便利な性質として「アフィン写像に対して普遍」というのがある。なんかまた難しい用語が出てきたけど、かみ砕いて言うと以下の通り。

  • ベジエ曲線を描いてから曲線全体を平行移動させるのと、先に制御点を平行移動してからベジエ曲線を描くのとでできる結果は同じ
  • 回転、拡大、縮小、鏡写しについても同様
  • そういう変換の組み合わせでも同様

この性質については、さっきの講義ページでは「ベジエ曲線とベジエ曲面6」に解説がある(これも PDF)。

実際に曲線を変換する場合は後者の方法、先に制御点を変換する方が楽に実装できる。

さらに、拡大の場合なんかは曲線全体を拡大すると困ることがある。曲線とは言っても実際には折れ線で近似していることを思い出そう。小さいうちは折れ線には見えなくても、拡大すると角の部分も拡大されるのでカクカクに見えてしまう。

そんな場合でも、後者の方法の場合は拡大した分だけ分割数を増やせば角は見えなくなる。曲線のアルゴリズムだけ決まっていて実際の精度は描画する時に決めれるので、必要に応じて精度を上げるということができるのだ。これが「ベクター画像は拡大してもギザギザがでてこない」という理由になってる。ベジエ曲線便利。

実用上はこういう理論を知らなくても必要なところだけ利用すればいいんだけど、数学を使うと「その性質が必ず成り立つ。絶対に大丈夫」という保証ができる。数学って何してるのかいまいち分かりにくいところがあるけど、こんなところに役に立ってる例があった。

あと、最初に言ったように canvas にはベジエ曲線を描く API があるので、これに実用上の意味はない。アルゴリズムを理解するためのサンプル。

そんなこんなで読書会は無事最後まで終了した。

最後に

思い出してみると、僕が初めて参加した勉強会が Kanasan.JS だった。それから2年以上たって、僕のプログラミングのレベルも上がったし、いろいろ発表するようにもなった。この勉強会を通して学んだことは大きかった。

Kanasan.JS はいろんな勉強会の中でもトップクラスの技術レベルだと思う。それもみんなで本を読んだりして勉強した結果だ。メンバーが入れ替わりながら何年も継続できているのは、この勉強会を大切に感じている人がいるからこそだと思う。そして、そういう流れを作ってくれた初代代表の Kanasan にはとても感謝しています。

今回でサイ本読書会が終わったので、次回以降は jQuery コードリーディングと単発企画ものを行う。これからも継続して、関西を代表する勉強会になればいいと思う。