2次元グラフィックスの課題
前回の2次元座標の移動・回転・拡大などの説明を行ったので、 今回はその応用として、座標回転拡大の理解がわかるプログラム作成の課題に 取り組んでもらう。

一筆書きで簡単な家の絵を、(-50,-50)並行移動して、60度刻みで回転し、少しづつ倍率を増やしてみた。
構造体の関数渡しなどもわかってほしいので、 以下に示すようなコードとしてみた。 (ただしGrWinを使用)
- grsample.cpp (文字コードUTF-8)
関数ポインタとコールバック
例年より授業の進度が速いので、 全体の総括の前に、追加ネタを加える。
関数ポインタは、オブジェクト指向の仮想関数の実装であったり、 イベント駆動型のプログラミングで重要なテクニックなので紹介する。
関数ポインタの基礎
基本的には、関数ポインタは以下のように使用する。 以下のサンプルプログラムでは、(*f)( 2 , 3 ) にて、fに代入されている関数を、 引数(2,3) にて呼び出す。
int fadd( int x , int y ) { return x + y ; } int fmul( int x , int y ) { return x * y ; } void main() { // 型は2つのintを引数を持つintを返り値とする関数へのポインタ int (*f)( int , int ) ; f = fadd ; // 関数名の後ろに丸カッコがない点に注目 printf( "%d¥n" , (*f)( 2 , 3 ) ) ; // 2+3=5 f = fmul ; printf( "%d¥n" , (*f)( 2 , 3 ) ) ; // 2*3=6 }
関数ポインタは、ライブラリを利用する際に、自分なりの変更を加えたい部分があったら、 その処理を関数で記述しておき、その関数のポインタをライブラリに渡す。 ライブラリは、必要に応じて関数ポインタを使って、関数を呼び出す。 このように、ライブラリの中から自分の渡した関数を呼び出してもらうのは、 「コールバック関数」と呼ばれる。
以下に簡単な例として、配列の最大データの添字を返すプログラムの例を示す。 この方法であれば、異なるデータの型でもコールバック関数を専用に作るだけで良い。
int intcmp( int* x , int* y ) { // 整数比較関数 if ( *x > *y ) return 1 ; else if ( *x < *y ) return -1 ; else return 0 ; } int vmax( void* array , // 配列先頭アドレス int size , // 配列データ件数 int sizeofdata , // 1件あたりのbyte数 int(*f)( void*,void* ) ) { // 比較関数 int i , max = 0 ; for( i = 0 ; i < size ; i++ ) if ( (*f)( array + max * sizeofdata , array + i * sizeofdata ) < 0 ) max = i ; return max ; } int idata[ 4 ] = { 11 , 33 , 22 , 44 } ; char sdata[ 4 ][ 4 ] = { "ab" , "bc" , "aa" , "c" } ; void main() { int m ; // intcmp関数を使って、idata から最大値を探す m = vmax( idata , 4 , sizeof(int) , intcmp ) ; printf( "%d" , idata[ m ] ) ; // strcmp関数を使って、sdata から最大値を探す m = vmax( sdata , 4 , sizeof(sdata[0]) , strcmp ) ; printf( "%s" , sdata[ m ] ) ; }
この方式をそのまま使った便利な関数が、C言語のクイックソートの標準関数 qsort( void* , sizt_t , size_t , int(*)( void*,void* ) ) である。この関数を使えば、データ比較用のコールバック関数を書くだけで、 配列の高速ソートが可能となる。
// LLVMなどの新しいC言語では、無名関数みたいな // block pointer ってぇのが使えるらしい。 int (^f)( int , int ) ; f = ^( int x , int y ) { return x + y ; } ; printf( "%d¥n" , f( 2 , 3 ) ) ; f = ^( int x , int y ) { return x * y ; } ; printf( "%d¥n" , f( 2 , 3 ) ) ;
オブジェクト指向での仮想関数
関数ポインタは、オブジェクト指向での仮想関数機能の実現に利用されている。
// 純粋仮想基底クラス class A { public: virtual void print() { printf( "A¥n" ) ; } } ; // 派生クラス A_int class A_int : public A { private: int data ; public: A_int( int x ) { data = x ; } virtual void print() { printf( "A_int : %d¥n" , data ) ; } } ; // 派生クラス A_str class A_str : public A { private: const char* data ; public: A_str( const char* x ) { data = x ; } virtual void print() { printf( "A_str : %s¥n" , data ) ; } } ; int main() { A aa ; A_int ai( 10 ) ; A_str as( "hello" ) ; // array[] には、異なる型のデータ(同じ基底クラス)が入ってる。 A* array[] = { &aa , &ai , &as } ; for( int i = 0 ; i < 3 ; i++ ) { array[ i ]-> print() ; } // 実行結果 // A // A_int : 10 // A_str : hello return 0 ; }
JavaScriptと無名関数
JavaScript では、イベント駆動のプログラムを実現するために、無名関数を利用することが多い。
var func ; func = function( x , y ) { return x + y ; } ; func( 2 , 3 ) ; // 答えは5 function foo( func ) { alert( func( 2 , 3 ) ) ; } foo( function(int x,int y) { return x * y ; } ) ; // alertで6が表示される
高専機構・情報セキュリティ講習会
12/2,12/3の高専機構主催の情報セキュリティ講習会に参加。
高専機構からの全体説明(12/2)
- 高専教職員の情報セキュリティ関係者向けのWebサイト公開準備中。
- 高専共通システム、Web給与明細から学認へと利用拡大中。
- 学認接続進行中。(Moodleで講習サイト)
- 情報セキュリティ実施(インシデント対応マニュアル、ユーザガイドライン、
情報の格付け)
- ソフトウェア管理(OS,Adobe,DreamSpark)
- 高専・両技科大の三機関ネットワーク網構築
- 次期(H30)校内LANシステム更新(WiFi含)
- 高専統一ネットワークシステム
三機関連携事業(グローバルイノベーションネットワーク:GIN)
各高専・両技科大のネットワーク(VLAN+L2SW)を整備し(H26/4月)、 同一規格のビデオ会議システムを構築し、 遠隔講義・テレビ会議・産学協同に活用予定。
Polycom RealPresence Group などを大講義室・中型教室・小会議室など 向けに準備
認証基盤システムとファイアウォール
認証サーバ(LDAP,Radius,Shibboleth IdP,UnifIDone)と、 Fortiシリーズを用いたFW,拠点間VPN,UTM(AntiVirus,Filter,IDS等)
各高専の取り組み事例報告
公式ホームページ管理運営(N高専)では、 情報系以外の教員でもメンテナンスできる体制づくりのために、 MovableTypeやPowerCMSを導入。 ページ管理の役割権限を役割に応じて細かく設定している様子。
ソフトウェア管理運営(G高専)では、 「AssetViewの報告だけで安心してはダメ」、 メーカー監査が入ると監査期間中のPC利用ができなくなるなどの リスクを十分理解する必要がある。 K高専では、管理担当者が発注/受領/メディア管理し、 利用者に必要に応じて貸し出す方式をとっている。 I高専では、各学科課にグループ担当管理者を設け、発注/受領/メディア管理。
校内LANシステム関係(A高専)の発表では、 H30の全高専校内LAN調達のモデルとして、 九州地区の高専で一括調達を行った際の経緯や流れが報告された。
グループディスカッション
各高専の参加者が5〜6人程度のグループに分かれ、グループディスカッションを 行った。私の参加したグループでは、教育用コンピュータシステム調達、情報倫 理問題点、学生のWiFi環境などについて情報交換が行われた。
教育システムでは、各校シンクライアント構成がとられている事例が多いが、 特殊な設定などでファットクライアントも一部あった。CAD系が絡んだりすると ブート遅延などもあり、各高専工夫があった。調達時は「起動 1 or 3分以内」 といった縛りを設けている様子。
情報倫理教育については、どの高専でも1年のリテラシーの中で 情報倫理(著作権・肖像権などを含む)を行っているが、 SNSでの情報が元になった処分が発生している。これらを踏まえ、高学年で 改めて問題点を踏まえた講習を実施する必要性を各高専で感じている様子。
校内WiFi環境については、導入済み・導入予定・禁止といった状態。 ネット接続による閲覧時の問題だけでなく、情報の持ち出しについても 議論することが重要。私物端末(BYOD)などの扱いも重要。 WiFiアクセス自由という高専もある。学生のWiFトラヒックはSINETに流さない などの対応校もあった。
他のグループでは、情報関連の人員をどう確保・仕事集中を防ぐかが 問題となっている様子。センター員もいくつかの学科のみという高専もある。 仕事を外注する事例もあったり、情報関係の技量の有無の問題など。
CGIの基本サンプル
専攻科実験でのRSSを用いた、情報活用の実験で、 パラメータの入力などの希望があったので、 最も簡単なCGIのサンプルを示す。
CGIサンプル
最初に、CGIを使えるようにするために、.htaccess ファイルにて、 CGI を使えるような設定を加える。
(( .htaccess )) Options ExecCGI AddType application/x-httpd-cgi .cgi
CGI モジュールを使う、極力短いサンプルコード。 セキュリティについては、考慮していないので十分に注意すること。
#!/usr/bin/perl # なお、このサンプルプログラムは、 # セキュリティについては考慮していない。 use CGI qw/:standard/ ; use Jcode ; my $cgi = new CGI ; # cgiのパラメータをもらう my $DATA = Jcode->new( param('DATA') )->utf8 ; # データ前後の空白を取る $DATA =~ s/\s+$// ; $DATA =~ s/^\s+// ; if ( "$DATA" eq "" ) { # パラメータが無い時は、ファイルから読み出す if ( -r "data.txt" ) { open( FH , "data.txt" ) or die( "Can't access for read" ) ; $DATA = <FH> ; close( FH ) ; } } else { # パラメータがあったら、ファイルに書き込む open( FH , ">data.txt" ) or die( "Can't access for write" ) ; print FH "$DATA\n" ; close( FH ) ; } # CGIの最初の決まり文句を出力 print header(-charset=>'UTF-8') ; print start_html(-title=>'Title', -charset=>'UTF-8', -encoding=>'UTF-8', -lang=>'UTF-8') ; # 画面に出力するHTMLの内容 print "<form method='GET' action='test.cgi'>\n" ; print "<input type='text' name='DATA' value='$DATA' />" ; print "</form>\n" ; print "入力値は<pre>$DATA</pre>\n" ; # CGIの終わりの決まり文句を出力 print end_html ;
PICAXEだってさ

PICの応用された新製品。 プログラム書き込みも、ステレオプラグを使ったシリアル通信でできて、 書き込み後は、単体で動かすことができるので、実際に動かすときは、 外付け部品ほどんどナシ。
プログラムも、GUI な環境で動く BASIC 言語っぽいもので書ける。
書き込みケーブル(1500円) (USB-ステレオプラグ/内部にUSB-Serialが入っているんだろうな)と、 ステレオプラグ-ライタの変換(320円)さえあれば、 PICAXE-08M2(8ピン)なら、1個240円とな。
cifsでマウントしたディレクトリをsamba共有かけたら…

バックアップ用のNASを、Debian/Linuxなサーバに接続して使っているが、 その一部フォルダを、サーバ利用者にバックアップ用に使ってもらおうと、 さらに samba で共有をかけた。 しかし、そのディレクトリ内部は、すべてファイル扱いされるトラブルが発生。
状況をメモ
NASは、下記のような設定で、automount されるようにしてある。 この /nfs/nas は、個別にアクセスができることは確認済み。
(( /etc/auto.nfs )) nas -fstype=cifs,rw,credentials=パスワードファイル, uid=xxxx,gid=xxxx,file_mode=0664,dir_mode=0775 ://XX.XX.XX.XX/path
このディレクトリを、他の利用者にも活用してもらうために、 samba のファイル共有で公開する。
# 直接 NAS を利用者に使わせるのは、NASの設定が面倒なのでパス
(( /etc/samba/smb.conf )) [nas] path = /nfs/nas write list = @group read list = @group create mask = 0775 directory mash 0775 force user = nobody browseable = yes
しかし、この公開されたファイル共有を Mac OS X で接続すると、 /nfs/nas の内部のファイルは見えるんだけど、ディレクトリが、 ファイル扱いを受けてしまい、ディレクトリ内部にアクセスできない…
(( 確認 )) iMac$ ls -al /Volumes/nas -rwxrwxr-x 0 xxxxxx xxxx ..... dir1 ← ディレクトリなのに... -rwxrwxr-x 0 xxxxxx xxxx ..... file1
ひとまず動いたのは…
色々設定を試したけど、どうも サーバ側の samba がおかしい様子。 ひとまず、以下の設定をはずしたら、ディレクトリとして 扱われるようにはなった。
(( /etc/samba/smb.conf )) - unix extensions = no + # unix extensions = no ← コメントアウト
演習室のノートパソコンのDHCP設定

学内のネットワークでは、学生さんのPCを学内有線LANに 勝手に接続させないために、ネットワーク接続設定を自動化 するための DHCP サーバを動かさない方針となっている。
しかし、演習室のノートパソコンは、気軽に移動先の実験室 で使ったりという運用を行うことから、ネットワーク接続に 設定を変更したりする機会も多い。
ただ、利用後にネットワークの設定を正しく元に戻して あれば問題はないが、慌てて設定を行うと単純ミスで 間違った設定になってしまうことも多かった。
そこで、演習室内のネットワークにて、MACアドレスを 利用して、登録PCにだけ対応IPアドレスを割り振るDHCPを 稼働させた。
(( /etc/dhcp/dhcpd.conf )) : host ei-n01 { hardware ethernet XX:XX:XX:XX:XX:XX ; fixed-address 10.120.11.YYY ; }
(専攻科実験)WebService::Simple
RSSフィード活用のプログラム作成のテーマだけれど、 もう少し応用も体験してほしいので、Google Search と関係づけてもらいたい。 でも、調べてみると Google Search API は、ajax からの活用を中心に するようになったので、ちょいと変換が必要で、少し面倒…
ひとまずは、WebService::Simple が簡単っぽい。 でも、Debian/testing のサーバでも、perl-module の命名習慣から推測し、 libwebservice-simple-perl といったパッケージを探すけど、見つからない。 しかたがないので、CPAN からインストール
# perl -MCPAN -e shell cpan[*]> install WebService::Simple
同じモジュール、自室サーバと学科仮想サーバに入れたけど、 仮想サーバは底力あるから速っ!!
WebService::Simpleを必要最小限動かす
まずは、Google などの検索エンジンで、AND や ORを使った、 細かい条件付き検索のテクニックを以下URLに示す。
上記のような検索キーワードでの検索を行うのであれば、 以下に示すように WebService::Simple を呼び出せば良い。
#!/usr/bin/perl use WebService::Simple ; use Data::Dumper ; use Jcode ; my $google = WebService::Simple->new( base_url => "http://ajax.googleapis.com/ajax/services/search/web", response_parser => "JSON", params => { v => "1.0", rsz=> "large" } ); my $response = $google->get( { q => Jcode->new( "ねこ site:tsaitoh.net" )->utf8 , start => 0 } ); my $xml = $response->parse_response ; # print Dumper $xml->{responseData}->{results}->[0] ; foreach my $item ( @{$xml->{responseData}->{results}} ) { print $item->{title}."\n" ; print $item->{url}."\n" ; }