ランダムドットステレオグラムアプリ - その11 [ランダムドットステレオグラムアプリ]
佳境に入ったランダムドットステレオグラムアプリ。実装に突入する。
読み込んだデータはすべて左から右、さらにそれが上から下へ並んでいると解釈する。
ほんとはGISのデータを読めるようにすれば地図の標高をステレオグラムに変換できるので、面白いんだけど、GISは汎用性が高く、構造が複雑で標高データに変換するだけでもめんどくさい。ファイル形式はXMLなのでFoundationフレームワークに備わったXMLの解析クラスを使えば簡単に読めるんだけど、それでもかなりの手間がかかる。気がむいたらやることにする(ということはやらないと言っているに等しいんだけど)。
もし、データが0をまたいだら、その「0」の輻輳がマーカの輻輳と一致するように最終的な描画を行う。これはまたあとで整理する。
深さ方向表現の感度とは、エレベーションマップの最大高さがどのくらい飛び出して見えるようにするか、という量でこれまでαという定数で代表させていた。これはユーザに別途指定してもらうか、指定がない場合にも表示できるようにデフォルトの値を決めておく。
テクスチャは曲線迷路を作ったときのをそのまま流用するが、今回は
そう考えるとテクスチャデータをfloatではなく8ビット符号なし整数にしたほうが相性はいいけど、補間のことがあるのでこっちはfloatのまま残しておくのがいいだろう。
縦横の入れ替えというのは、Height Mapの2次元配列を90°回転するかどうかを指定する。上下反転は単にデータが上から並んでるか下から並んでるかの違いを吸収するためのもの。どちらもデフォルトでは行列を表示するのと同じにする。
縦方向のグリッドというのは決まった高さに対応する輻輳距離に細線でグリッドを引く。上に金網を張ったような表現になって目の調整がやりやすくなる場合がある。いつもそうとは限らないけど。
今回も編集はないアプリなので、同じ悩みを抱えることになる。
今回は「新規」はなしで、「開く」だけにするか。まず最初にエレベーションマップのファイルを指定して始めるというかたち。そうすると、「開く」のダイアログでほかのパラメータも全部一緒に指定するようになっていないといけない。
で、開いてしまうとすぐステレオグラムをそのパラメータにしたがって生成して表示する。そしてパラメータ変更のためにパネルを表示して、そのうえでパラメータを書き換えると表示に反映させる、というのがいいだろうな。あまり大きなマップだとFFTが律速して、テクスチャ生成に時間がかかることになる。中間配列を使うことにしたので、深さ方向表現の感度を変えない限りはテクスチャを変更してもマッピングはそれほど重くないはず。
それほど複雑なアプリではないので、こんなもんでいいだろう。
さくっと実装してみよう。って、今から始めると徹夜になってしまう。い、いかん、いかん。明日は早いのでさっさと寝ることにする。
2 実装
さて、実装。2.1 入力データの形式
Height mapがユーザから与えられるとする。その方法は- グレーのビットマップイメージ(具体的にはTIFFやPNGなど)
- CSV形式
- 適当なデリミタを持ったテキスト形式
読み込んだデータはすべて左から右、さらにそれが上から下へ並んでいると解釈する。
ほんとはGISのデータを読めるようにすれば地図の標高をステレオグラムに変換できるので、面白いんだけど、GISは汎用性が高く、構造が複雑で標高データに変換するだけでもめんどくさい。ファイル形式はXMLなのでFoundationフレームワークに備わったXMLの解析クラスを使えば簡単に読めるんだけど、それでもかなりの手間がかかる。気がむいたらやることにする(ということはやらないと言っているに等しいんだけど)。
2.2 エレベーションマップの内部形式
読み込んだエレベーションマップは内部形式に変換する。といってもそんな大げさなものではなく、floatの配列。その際- 配列の縦横の長さ
- 値の最大値と最小値
- 深さ方向表現の感度
もし、データが0をまたいだら、その「0」の輻輳がマーカの輻輳と一致するように最終的な描画を行う。これはまたあとで整理する。
深さ方向表現の感度とは、エレベーションマップの最大高さがどのくらい飛び出して見えるようにするか、という量でこれまでαという定数で代表させていた。これはユーザに別途指定してもらうか、指定がない場合にも表示できるようにデフォルトの値を決めておく。
2.3 表示の中間形式
アルゴリズムの整理のところで導入したD(p, q)の配列を作る。これもfloatの配列で十分。アルゴリズム通りに実装できるので、それほど問題はないだろう。2.4 テクスチャデータ
テクスチャデータfloatの配列として生成する。値は[0, 1]区間におさめる。テクスチャは曲線迷路を作ったときのをそのまま流用するが、今回は
- グレー
- カラー(RGB)
- バイナリ
2.4.1 グレー
グレーは曲線迷路とまったく同じに生成する。ただし、生成後規格化する、つまり- 最小値を0
- 最大値を1
2.4.2 カラー
カラーはRGB3チャンネルそれぞれにグレー生成と同じことをするだけである。2.4.3 バイナリ
バイナリはグレーを生成した後、平均値を閾値にして0と1に2値化する。平均値はグレーを生成する過程でFourier変換側の原点の値を覚えておけばいい。2.4.4 生成のパラメータ
パラメータは- 画像の幅(輻輳の距離)
- グレー/カラー/バイナリの選択
- 縦横の粒度
2.4.5 外部データの使用
テクスチャを自動生成するのではなく、外部の画像データを読み込んでそれをテクスチャとして利用できるようにしたほうがいいだろう。しかしこの場合、こまかな問題がいろいろおこる。- エレベーションマップの高さと画像データの高さが違う場合(というかそれが普通だろう)にどうするか
- 画像データの横幅と輻輳距離を合わせるかどうか
- 組み合わせによって縦横比を保持できなくなるが、保持するようなオプションを設けるか
- 場合によっては輻輳が大きすぎたり小さすぎたりするのをどう扱うか
2.5 ステレオグラムデータ
ステレオグラムS(p, q)は直接表示できるようにNSBitmapImageRepのサブクラスとして実装するのがいいだろう。しかしNSBitmapImageRepはcomponentの型がfloatのカラーデータをサポートしてないので、RGB各8ビットの形式に変換する必要がある。ということはどうせだからグレーもバイナリも8ビットに統一したほうが楽ではある。そう考えるとテクスチャデータをfloatではなく8ビット符号なし整数にしたほうが相性はいいけど、補間のことがあるのでこっちはfloatのまま残しておくのがいいだろう。
2.5.1 NSBitmapImageRepのサブクラス化
また例のごとくサブクラスにするのがいいか、カテゴリでいいか、それとも新しいクラスでNSBitmapImageRepを保持しているのがいいか、は実際にコーディングをする段階で決めることにする。今回はカテゴリで十分という気もする。2.6 表示のオプション
その他に表示に関連してユーザに指定してもらう必要のあるパラメータがある。- 縦横の入れ替え/上下の反転
- 縦方向のグリッド
- その他
縦横の入れ替えというのは、Height Mapの2次元配列を90°回転するかどうかを指定する。上下反転は単にデータが上から並んでるか下から並んでるかの違いを吸収するためのもの。どちらもデフォルトでは行列を表示するのと同じにする。
縦方向のグリッドというのは決まった高さに対応する輻輳距離に細線でグリッドを引く。上に金網を張ったような表現になって目の調整がやりやすくなる場合がある。いつもそうとは限らないけど。
2.7 ユーザインターフェイス
アプリを書くたびにユーザインターフェイスをどうするか、というのはいつも悩む。なるべく素直にドキュメントアプリにしたいけど、以前の迷路生成アプリのように、なにかを作るだけで編集しないアプリというのはドキュメントスタイルからちょっとはずれることになって、それをどういう表現にするか、というのは難しい。迷路生成アプリは「新規メニュー」でいったん生成のために基礎となるデータをまず入力させるダイアログを表示している。これがMacOSXアプリらしくない動作になっている。今回も編集はないアプリなので、同じ悩みを抱えることになる。
今回は「新規」はなしで、「開く」だけにするか。まず最初にエレベーションマップのファイルを指定して始めるというかたち。そうすると、「開く」のダイアログでほかのパラメータも全部一緒に指定するようになっていないといけない。
で、開いてしまうとすぐステレオグラムをそのパラメータにしたがって生成して表示する。そしてパラメータ変更のためにパネルを表示して、そのうえでパラメータを書き換えると表示に反映させる、というのがいいだろうな。あまり大きなマップだとFFTが律速して、テクスチャ生成に時間がかかることになる。中間配列を使うことにしたので、深さ方向表現の感度を変えない限りはテクスチャを変更してもマッピングはそれほど重くないはず。
それほど複雑なアプリではないので、こんなもんでいいだろう。
さくっと実装してみよう。って、今から始めると徹夜になってしまう。い、いかん、いかん。明日は早いのでさっさと寝ることにする。
2011-07-24 21:42
nice!(0)
コメント(0)
トラックバック(0)
コメント 0