PPPUC++#14
12. A Display Model
"The world was black and white then. [It] didn't turn color until sometime in the 1930s."
漫画カルビン&ホッブスでの父との会話ですね。「なんで昔の写真は白黒なの?」というカルビンの質問に対するもの。
「で、じゃあなんで(1930年になってから)写真も色つきにならなかったの?」「そりゃあ簡単さ、それは白黒の世界を撮ったカラー写真だからさ」
こんなとーちゃんでいたいです(迷惑)
12.1 Why Graphics?
- グラフィックスの本でも無いのになぜ4章分もGUI?
- プログラミングの重要な部分を浮き彫りにするテーマなのです
- ほんまデスか?
- プログラミングの重要な部分を浮き彫りにするテーマなのです
-
- 有用: 多くの領域で図的な表現が本質だったり重要だったり。たとえば科学技術演算の結果を数値だけで理解するのは退屈だし困難
- たのしい!: いやまちがいなく。全然使い物にならなくても結果が目に見えるのは楽しいです。そして楽しいと理解が進みます
- 読むのに良い: 結果と一対一対応するので、同レベルの複雑度の他のコードに比べてグラフィックスのコードは読みやすい
- 設計の例: 関数の設計、抽象レイヤ、ライブラリの構成、など設計の例としても好例
- オブジェクト指向: 画面に表示される「モノ」と一対一対応するため、非常に判りやすい例になる
- 複雑な概念もある: 教材として申し分ない
12.2 A display model
12.3 A first example
- ちょっとした連結線の例
- キモは単なるクラスの定義なのです
#include "Simple_window.h" // window lib #include "Graph.h" // graphics library int main() { using namespace Graph_lib; Point tl(100,100); // 左上座標. // tlはウィンドウの位置らしい。なんか変態的 Simple_window win(tl, 600, 400, "Canvas"); Polygon poly; // make a shape (a polygon) poly.add(Point(300,200)); poly.add(Point(350,100)); poly.add(Point(400,200)); poly.set_color(Color::red); win.attach(poly); win.wait_for_button(); // push next button! }
- まあ説明の必要も無いほどにシンプル。まさに三輪車、補助輪付自転車。
- tlがフレームの位置か描画の位置か、っておそらくフレームの位置でしょうね
- 右上にNEXTというボタンが出るらしく, wait_for_button()でこれを待ってくれるらしい。
- これを使って紙芝居が作れるみたいです
- 16章でこの補助輪を外すそうです。楽しみですな
- クローズボタンとかはウィンドウシステムが無料でくれたものですがなかなか使いでがありますよー、とか
12.4 Using a GUI library
- OS直のグラフィックとかGUI機構は使いません
- 一つはやはり互換性。プラットフォーム依存しないため
- もう一つは楽をするため。直駆動はかなり大変。
- 本質的に複雑なことを、単純な言葉で言い表すのは大変なのです
- ところが、残念なことにC++標準GUIライブラリというのは無いんですね
- 数あるGUIライブラリの中から FLTKを選びました http://www.fltk.org/
- 更にそれに" Our interface library "で皮を被せてもうすこし可搬性と可読性を上げます
- そういえば以前に少しだけいじってみたことがありました http://d.hatena.ne.jp/tkuro/20090528/1243489842
- まあFLTK自体がほとんどのプラットフォームで動くので可搬性はどうでもよさそうですが、Mr.S的にはこのラッパライブラリのアイディアが伝えたいっぽい
- 更にそれに" Our interface library "で皮を被せてもうすこし可搬性と可読性を上げます
- このラッパライブラリは非常に小さく600行くらい
- 全体としてはこんなイメージになります
- 16章ではコールバック関数についてもやります
12.5 Coordinates
- コンピュータの画面はピクセルで構成された矩形領域です
- ピクセルは画面上の小さな点
- 場所は(x,y)の対で表されます
- 左 上 が原点で、y座標は普通の数学とは逆。数字が大きいほど下になってます
- コンピュータグラフィックスではよくあること
- 実際反対でも特に問題は無いはずなのですが・・・
- 実際GLやQuartzの座標系はそうなってますね
- コンピュータ屋はついつい無意識に画面座標にターミナルでの表示方向やメモリアドレスをマップしてしまうのでこうなってしまうのでしょうね。
- テキストを書く場合は確かにチト問題あるかも
- Mr.Sもコンピュータ屋なので、
頭が凝り固まってコンピュータでよく使われるプログラムの都合にあわせて、「スクリーンとかウィンドウっていろんなサイズあるからさ、左上の点ってほら共通じゃん」とか頭悪い素晴らしい説明をしています。-
いろんなサイズあるから何? 左下が共通でも同じだろアホか。いやあ Mr.Sっておもしろいです
-
- ウィンドウってのはスクリーンを切り取った仮想スクリーンだよ、とか
- ちなみにコード中で指定したサイズはウィンドウ周りのタイトルバーとかボタンとかの領域は含んでないよ、とかでした
12.6 Shapes
- クラス階層はこんな感じ
12.7 Using Shape primitives
- Mr.S自慢のライブラリで何ができるか見ていきましょう
- 例の紙芝居方式で足していく事ができてラクチン!
12.7.1 Graphics headers and main
- まずはヘッダのinclude。
#include "Window.h" // a plain window. if you want NEXT button, include "Simple_window.h" instead #include "Graph.h"
- Graph_lib namespaceの中に詰め込んでますので、using namespaceなりご自由に(ただし既にバッティングします)
12.7.2 An almost blank window
- この先は、紙芝居のためか、とりあえずSimple_Windowしか考えないみたい
- 単に Simple_windowを作って Simple_window::wait_for_button()するとウィンドウがdraw()されて、NEXTボタン押しを待つようになってます
- Mr.Sのラップトップのデスクトップ画面が出てます
- Mr.Sは自分のデスクトップの奇麗さを自慢したいらしいのですが、そんなことはどうでもよろしい
- どうもフランス旅行に行ったのを自慢したいらしいのですが、やっぱりどうでもよろしい
- まったく面白いオッサンだ
- さあ気を取り直して・・・
12.7.3 Axis
- やっぱ何か表示したい。
- 遊んでる訳じゃあないんだから、やっぱりまじめな事をするのダ
- となるとやっぱり座標よね。マジメっぽい
- ということで、便利そう
で、実際にはあんまり使いどころの無いな座標表示 - ナイスなグラフ表示なら内容無くても(ry!!
- 飛ばしてるなMr.S
{ Axis xs(Axis::x, Point(50, 350), 530, 90, "x axis"); // x or y, 座標原点, 長さ, ノッチの数, ラベル Axis ys(Axis::y, Point(50, 350), 290, 20, "縦だだだ"); xs.set_color(Color::blue); ys.set_color(Color::black); xs.label.set_color(Color::dark_green); win.attach(xs); win.attach(ys); win.wait_for_button(); }
- とくに説明無いけれども一応destructされると画面から消えるのでこのようにブロックに囲っとくと紙芝居しやすい
- 日本語でター!
- ついでに 90とかしてやったら結構誤差誤差のバグっぽいですね
- ラベルの色だけとかも変えられる。結構スゴい
- 適当に遊んでたら、次のページに "We don't actually think that it is a good idea to use differnet colors for x and y axes.".... スミマセン
- "In particular, novices tend to use color with more enthusiasm than taste" ........ oI~~~~z
12.7.4 Graphing a function
- 関数系も書けるのですね
Function fsine(sin, 0, 100, Point(50, 150), 1000 ,50, 50); // func, range, start, point, scalex, scaley; Function fsinc(sinc, 0.01, 100, Point(50, 250), 1000 ,20, 90); fsinc.set_color(Color::dark_red); fsine.set_color(Color::dark_cyan); win.attach(fsine); win.attach(fsinc); win.wait_for_button();
12.7.5 Polygons
- これは既にやった。
- データ表現ではないもの、普通に多角形。ポリゴン
12.7.6 Rectangles
- 矩形です。
- 現実世界に沢山あります。角が丸まったヤツも(Steve Jobsによると)沢山あります
Rectangle rect(Point(200, 200), 100, 50); win.attach(rect); win.set_label("rectangle"); win.wait_for_button();
- 閉じたポリラインでも書けるよ、という話
12.7.7 Fill
- 塗りつぶしや線種など
rect.set_fill_color(Color::yellow); poly.set_style(Line_style(Line_style::dash, 4)); poly_rect.set_style(Line_style(Line_style::dash, 2)); poly_rect.set_fill_color(Color::green); win.wait_for_button();
- いや実際おもそろい
12.7.8 Text
- テキストの描画が無いと完全じゃない
- 線で書くのはダメ。敷居が高くなりすぎる
Text t(Point(180, 150), "Hello, graphical world!"); t.set_font_size(30); win.attach(t); win.wait_for_button();
- 実は Axisのラベルもテキストオブジェクトだったり
- もちろんフォントや装飾だって変えられます
12.7.9 Images
- まあ絵ですね
Image ii(Point(100,50), "hoge.jpg"); win.attach(ii); :
- あとから .move()で動かす事もできます
12.8 Getting this to run
- ウィンドウの作り方、その中での図形の描画についてざっと見てきました
- でも実際に動かすためにはここにあるコード以上にいろいろ必要です
- インターフェイスライブラリ、FLTKライブラリ、
- 愛、希望、かけら、、、、(寝ぼけてます)
- いろんなファイルが関わってるんだなーという雰囲気
- 付録Dに統合方法が書いてあるっぽい。読んでないけど。。。
12.8.1 Source files
- 5つのヘッダと、3つの実装ファイル
-
- そしてあまたの
アホなバグ - 予想通り以前に文句言ってた #define vector Vector が悪さをしてわかりにきー変なエラー出たり、templateのtype指定が抜けてたりとか、コンストラクタがheaderと実装ファイルで二重定義とか、unsigned と signedが混在してwarningだらけとか、Fl_Windowに入った直後 make_currentしてないからリサイズとかしないとShapeが表示されないとか、初期化順が不規則とか、Windowが安易にusing namespaceしてるせいでバッティングしてるとか、もう
アホかと - どーどー。教育的配慮なんだよ。教育的配慮。全く触った事ない人が全部をなんとかできるとは到底思えないが・・・
- そしてあまたの
- 要望あればgithubにでも上げておきます.
-
- 手品の種明かしは16章までおあずけ、だそうです。