CG プログラミング論 平成 26 年 5 月 26 日 第6章.図形の移動 【学習のねらい】 ① 今週は、図形を移動する方法を学習します。具体的には、「x 軸(水平軸)に対する対 称移動」、「y軸に対する対称移動」、「原点に対する対称移動」そして「原点の回りの 回転移動」の 4 種類の移動方法です。これらを用いれば様々な(対称性を持った)図 形を容易に描くことができる事が分かるはずです。そうすれば CG への興味が益々湧 いてくることと思います。いずれもプリントをよく読めば確実に理解できる内容なの で、 「対称移動」等の言葉に惑わされずに落ち着いて学習して下さい。 6-1 多角形の描画 まず、移動する基となる図形として次の様な多角形を描きましょう。 (-30,90) y軸 (30,90) (0,60) (-30,30) (30,30) x軸 (0,0) これまでの学習でもう慣れていることと思いますが、これをコンピュータ画面上に描く場 合には、次のように左上隅が原点である事を考慮しなければなりません。グラフの原点を (X0,Y0)とすると、各点のコンピュータ上の座標は下の点線枠内の様になります。 (0,0) (X0-30,Y0-90) (-30,90) X軸 <コンピュータ上の座標> y軸 (30,90) (X0+30,Y0-90) (0,60) (X0,Y0-60) (-30,30) (30,30) (X0+30,Y0-30) (X0-30,Y0-30) Y軸 (0,0) 53 x軸 (X0,Y0) CG プログラミング論 平成 26 年 5 月 26 日 各点の座標が分かれば図形を描くことは容易です。以下では上のような多角形の描画に、 drawPolygon(x,y,N)、 x,y:各点の x,y 座標を格納した配列、 N:点の数 というメソッドを用います。 ※ このメソッドが呼び出されると、点(x[0],y[0]) 、点(x[1],x[1])、・・・、点(x[N-1],y[N-1]) と順に直線で結んで行き、最後に再び点(x[0],y[0])に戻ってきます。これにより、N 点 を結ぶ多角形が描かれます( 「プログラミング」テキスト pp.209~210 参照) 。 【基礎課題 6-1】 上で説明した多角形を描くプログラムを作成しましょう。 このプログラムを次のように記述しました。空欄を埋めてプログラムを完成させて下さい。 配列の宣言については、「プログラミング」テキスト pp.95~97 参照。 void DrawGraphics(Graphics g) { int[] x={0,30,30,0,-30,-30}; //多角形のx座標の定義 int[] y={0,30,90,60,90,30}; //多角形のy座標の定義 int N=6; //データ数(多角形の頂点の数) int x0=100; //原点のx座標(コンピュータ上) int y0=100; //原点のy座標(コンピュータ上) int[] xp=new int[N]; //コンピュータ上のx座標を格納する配列 int[] yp=new int[N]; //コンピュータ上のy座標を格納する配列 g.setColor(Color.BLUE); //描画色を青に設定 for(int i=0; i<N; i++) { 頂点の座標をコンピュータ上の座 xp[i]= x0+x[i] ; yp[i]= ① ; 標(xp[i],yp[i])(i=0~N-1)に変換 } g.drawPolygon(xp,yp,N); //多角形を描画 } 54 CG プログラミング論 平成 26 年 5 月 26 日 6-2 対称移動① - x軸(水平軸)に対する対称移動 ある図形を、x軸に関して折り返した図形(下の点線で描かれた図形)をx軸に関して 対称な図形、あるいはx軸に対して対称移動した図形と言います。 (-30,90) y軸 (30,90) (0,60) (-30,30) (30,30) (0,0) (-30,-30) x軸 y座標が逆符号 (30,-30) (0,-60) (-30,-90) (30,-90) 上の図を見ると、x軸対称な図形と元の図形を比べると、対応する頂点のy座標が逆符 号になっている事が分かります。したがって、x軸対称な図形は元となる図形の各点のy 座標を逆符号にするだけで描ける事が分かります。 【基礎課題 6-2】 【基礎課題 6-1】のプログラムを修正して、次ページのようにx軸(水平軸)に対して対 称移動した図形も(併せて)描くようにしましょう。 このプログラムは次ページの様になります。プログラムを見ると分かるとおり、これは 【基礎課題 6-1】のプログラムに、x軸対称な図形を描く部分(点線枠内)を追加しただけ です。空欄①を埋めてプログラムを完成させて下さい。 55 CG プログラミング論 平成 26 年 5 月 26 日 void DrawGraphics(Graphics g) { int[] x={0,30,30,0,-30,-30}; //多角形のx座標の定義 int[] y={0,30,90,60,90,30}; //多角形のy座標の定義 int N=6; //データ数(多角形の頂点の数) int x0=100; //原点のx座標(コンピュータ上) int y0=100; //原点のy座標(コンピュータ上) int[] xp=new int[N]; //コンピュータ上のx座標を格納する配列 int[] yp=new int[N]; //コンピュータ上のy座標を格納する配列 g.setColor(Color.BLUE); //描画色を青に設定 //図形(多角形)の描画 for(int i=0; i<N; i++) { xp[i]= x0+x[i] ; yp[i]= ; } g.drawPolygon(xp,yp,N); //多角形を描画 //x軸対称な図形の描画 for(int i=0; i<N; i++) { xp[i]= x0+x[i] ; yp[i]= ① ; } g.drawPolygon(xp,yp,N); //多角形を描画 } 56 新たに追加した部分 CG プログラミング論 平成 26 年 5 月 26 日 6-3 対称移動② - y軸(垂直軸)に対する対称移動 前節に続いて今度はy軸(垂直軸)に対する対称移動を考えましょう。下の左半分の点 線図形が、 (右半分の)図形をy軸に対して対称移動したものです。 y軸 (-90,30) (-30,30) (30,30) (-60,0) (-90,-30) (90,30) (60,0) (-30,-30) (30,-30) x軸 (90,-30) 図より、y軸対称な図形と元の図形を比べると、対応する頂点のx座標が逆符号になって いる事が分かります。したがって、y軸対称な図形は元となる図形の各点のx座標を逆符 号にするだけで描ける事が分かります。 【基礎課題 6-3】 【基礎課題 6-1】のプログラムを修正して、上図で与えられた図形のy軸対称な図形を(元 の図形と共に)描くプログラムを作成しましょう。下がその実行結果です。 57 CG プログラミング論 平成 26 年 5 月 26 日 このプログラムは次のようになります。図形が変わったことに応じてその座標が下線部 の様に( 【基礎課題 6-1】から)変わりますが、あとは、点線枠部分を追加しただけです。 空欄①、②を埋めてプログラムを完成させて下さい。 void DrawGraphics(Graphics g) { int[] x={0,30,90,60,90,30}; //多角形のx座標の定義 int[] y={0,-30,-30,0,30,30}; //多角形のy座標の定義 int N=6; //データ数(多角形の頂点の数) int x0=100; //原点のx座標(コンピュータ上) int y0=100; //原点のy座標(コンピュータ上) int[] xp=new int[N]; //コンピュータ上のx座標を格納する配列 int[] yp=new int[N]; //コンピュータ上のy座標を格納する配列 g.setColor(Color.BLUE); //描画色を青に設定 //図形(多角形)の描画 for(int i=0; i<N; i++) { xp[i]= x0+x[i] ; yp[i]= y0-y[i] ; } g.drawPolygon(xp,yp,N); //多角形を描画 //y軸対称な図形の描画 for(int i=0; i<N; i++) { xp[i]= ① ; yp[i]= ; ② } g.drawPolygon(xp,yp,N); //多角形を描画 } 58 CG プログラミング論 平成 26 年 5 月 26 日 6-4 対称移動③ - 原点に対する対称移動 対称移動の最後の例として、原点に対する対称移動を採り上げましょう。左下の点線図 形が、 (右上の)図形を原点に対して対称移動したものです。 y軸 (30,90) (0,60) (30,30) x軸 (-30,-30) (0,-60) (-30,-90) 図より、原点対称な図形と元の図形を比べると、対応する頂点の(x,y)座標が共に逆符 号になっている事が分かります。したがって、原点対称な図形は元となる図形の各点の(x, y)座標を共に逆符号にすることで描ける事が分かります。 【基礎課題 6-4】 【基礎課題 6-1】のプログラムを 修正して、上図で与えられた図 形の原点対称な図形を(元の図 形と共に)描くプログラムを作 成しましょう。左がその実行結 果です。 59 CG プログラミング論 平成 26 年 5 月 26 日 このプログラムは次のようになります。図形が変わったことに応じてその座標および多 角形の頂点数 N が下線部の様に( 【基礎課題 6-1】から)変わりますが、あとは、点線枠部 分を追加しただけです。空欄①、②を埋めてプログラムを完成させて下さい。 void DrawGraphics(Graphics g) { int[] x={0,30,30,0}; //多角形のx座標の定義 int[] y={0,30,90,60}; //多角形のy座標の定義 int N=4; //データ数(多角形の頂点の数) int x0=100; //原点のx座標(コンピュータ上) int y0=100; //原点のy座標(コンピュータ上) int[] xp=new int[N]; //コンピュータ上のx座標を格納する配列 int[] yp=new int[N]; //コンピュータ上のy座標を格納する配列 g.setColor(Color.BLUE); //描画色を青に設定 //図形(多角形)の描画 for(int i=0; i<N; i++) { xp[i]=x0+x[i]; yp[i]=y0-y[i]; } g.drawPolygon(xp,yp,N); //多角形を描画 //原点対称な図形の描画 for(int i=0; i<N; i++) { xp[i]= ① ; yp[i]= ; ② } g.drawPolygon(xp,yp,N); //多角形を描画 } 60 CG プログラミング論 平成 26 年 5 月 26 日 6-5 対称移動の組み合わせ 何らかの対称性を持つ図形は、対称移動を組み合わせる事で(少ない労力で)描くことが できます。下は、右上の図形(斜線領域)の図形から、これまで学習したx軸対称、y軸 対称そして原点対称な図形を作成し、合成したものです。 (-30,90) y軸 (30,90) y軸対称 (0,60) (-30,30) (30,30) x軸 (-30,-30) 原点対称 (30,-30) (0,-60) (-30,-90) x軸対称 (30,-90) 【基礎課題 6-5】 上図の図形を(対称移動を組み合わせることで)描画するプログラムを作成しましょう。 61 CG プログラミング論 平成 26 年 5 月 26 日 このプログラムは次のように記述できます。図から分かるとおり、基本的には【基礎課題 6-4】のプログラムに、x軸対称な図形およびy軸対称な図形を描く部分を追加したものに なります。これまでの総復習として、下の空欄①~⑥を埋めてプログラムを完成させて下 さい。 void DrawGraphics(Graphics g) { int[] x={0,30,30,0}; //多角形のx座標の定義 int[] y={0,30,90,60}; //多角形のy座標の定義 int N=4; //データ数(多角形の頂点の数) int x0=100; //原点のx座標(コンピュータ上) int y0=100; //原点のy座標(コンピュータ上) int[] xp=new int[N]; //コンピュータ上のx座標を格納する配列 int[] yp=new int[N]; //コンピュータ上のy座標を格納する配列 g.setColor(Color.BLUE); //描画色を青に設定 //図形(多角形)の描画 for(int i=0; i<N; i++) { 【基礎課題 6-4】に追加し xp[i]=x0+x[i]; yp[i]=y0-y[i]; た部分 } g.drawPolygon(xp,yp,N); //多角形を描画 //x軸対称な図形の描画 for(int i=0; i<N; i++) { ① xp[i]= ; yp[i]= ② ; xp[i]= ③ ; yp[i]= ④ ; } g.drawPolygon(xp,yp,N); //多角形を描画 //y軸対称な図形の描画 for(int i=0; i<N; i++) { } g.drawPolygon(xp,yp,N); //多角形を描画 //原点対称な図形の描画 for(int i=0; i<N; i++) { xp[i]= yp[i]= ⑤ ⑥ ; ; } g.drawPolygon(xp,yp,N); //多角形を描画 } 62 CG プログラミング論 平成 26 年 5 月 26 日 6-6 原点回りの回転移動 本章の最後に、原点回りの回転移動を考えましょう。 左のように、点 A(x,y)を角度θだけ回転させ y軸 た時の点を B とすると、その座標(x',y')は次の B(x',y') ように求められます。 x' x cos y sin θ y ' x sin y cos A(x,y) x軸 回転移動を記述するのに必要な式はこれだけ です。 【基礎課題 6-6】 上の回転移動の式を利用して、次のように三角形を 90°だけ回転させて表示させるプロ グラムを作成しましょう。 (x1',y1') 対応する頂点の座標は例えば次のように y軸 なっています。 (x1,y1) x1' x1 cos y1sin 90° y1' x1sin y1 cos x軸 90 / 2 作成するプログラムの実行 結果は左の通りです。 63 CG プログラミング論 平成 26 年 5 月 26 日 このプログラムを次のように記述しました。プログラムの意味はコメントから理解でき るでしょう。下の点線枠部分がθ=90°(π/2)だけ回転させた図形を描く部分です。 void DrawGraphics(Graphics g) { int[] x={0,50,50}; //多角形(今の場合三角形)のx座標の定義 int[] y={0,0,50}; //多角形(今の場合三角形)のy座標の定義 int N=3; //データ数(多角形の頂点の数) int x0=100; //原点のx座標(コンピュータ上) int y0=100; //原点のy座標(コンピュータ上) int[] xp=new int[N]; //コンピュータ上のx座標を格納する配列 int[] yp=new int[N]; //コンピュータ上のy座標を格納する配列 g.setColor(Color.BLUE); //描画色を青に設定 //図形(多角形)の描画 double x_rot,y_rot,theta; theta=0; //角度θ=0 for(int i=0; i<N; i++) { x_rot=x[i]*Math.cos(theta)-y[i]*Math.sin(theta);//回転後のx座標 y_rot=x[i]*Math.sin(theta)+y[i]*Math.cos(theta);//回転後のy座標 xp[i]=x0+(int) x_rot; コンピュータ上の座標(xp,yp)へ変換 yp[i]=y0-(int) y_rot; } g.drawPolygon(xp,yp,N); //多角形を描画 theta=Math.PI/2; //角度θ=π/2(90°) for(int i=0; i<N; i++) { x_rot=x[i]*Math.cos(theta)-y[i]*Math.sin(theta);//回転後のx座標 y_rot=x[i]*Math.sin(theta)+y[i]*Math.cos(theta);//回転後のy座標 xp[i]=x0+(int) x_rot; yp[i]=y0-(int) y_rot; } g.drawPolygon(xp,yp,N); //多角形を描画 } 回転図形を描く部分 まず、このプログラムの動作結果を確認して下さい。 次に、このプログラムを利用(改良)して、次ページのような結果を与えるプログラムを作 成しました。図から分かるとおり、これは、90°(π/2)ずつ回転させた三角形を4つ表示さ せたものです。 64 CG プログラミング論 平成 26 年 5 月 26 日 このプログラムを次のように作成しました。空欄①を埋めてプログラムを完成させて下 さい。 void DrawGraphics(Graphics g) { int[] x={0,50,50}; //多角形のx座標の定義 int[] y={0,0,50}; //多角形のy座標の定義 int N=3; //データ数(多角形の頂点の数) int x0=100; //原点のx座標(コンピュータ上) int y0=100; //原点のy座標(コンピュータ上) int[] xp=new int[N]; //コンピュータ上のx座標を格納する配列 int[] yp=new int[N]; //コンピュータ上のy座標を格納する配列 g.setColor(Color.BLUE); //描画色を青に設定 //図形(多角形)の描画 double x_rot,y_rot,theta,d_theta; d_theta= ; //角度θの刻み幅 ① for(int j=0;j<4;j++) { //4つの三角形を繰り返し処理で描画 theta=d_theta*j; //角度θ for(int i=0; i<N; i++) { x_rot=x[i]*Math.cos(theta)-y[i]*Math.sin(theta); y_rot=x[i]*Math.sin(theta)+y[i]*Math.cos(theta); xp[i]=x0+(int) (x_rot); yp[i]=y0-(int) (y_rot); } g.drawPolygon(xp,yp,N); //多角形を描画 } } 65 CG プログラミング論 平成 26 年 5 月 26 日 【応用課題 6-A】 【基礎課題 6-6】のプログラムを 改良して右のような(風車のよう な)図形を描きましょう。今度は 三角形を 12 個描き、三角形内を塗 りつぶしています。 このプログラムは【基礎課題 6-6】から下のように空欄①と下線 部を修正し、点線枠②を(三角形 を色塗りする様に)修正する事で 実現できます。空欄①を埋め、修 正後の点線枠②を記述して下さい。 void DrawGraphics(Graphics g) { int[] x={0,50,50}; //多角形のx座標の定義 int[] y={0,0,50}; //多角形のy座標の定義 int N=3; //データ数(多角形の頂点の数) int x0=100; //原点のx座標(コンピュータ上) int y0=100; //原点のy座標(コンピュータ上) int[] xp=new int[N]; //コンピュータ上のx座標を格納する配列 int[] yp=new int[N]; //コンピュータ上のy座標を格納する配列 g.setColor(Color.BLUE); //描画色を青に設定 //図形(多角形)の描画 double x_rot,y_rot,theta,d_theta; d_theta= ; //角度θの刻み幅 ① for(int j=0;j<12;j++) { theta=d_theta*j; //角度θ for(int i=0; i<N; i++) { x_rot=x[i]*Math.cos(theta)-y[i]*Math.sin(theta); y_rot=x[i]*Math.sin(theta)+y[i]*Math.cos(theta); xp[i]=x0+(int) (x_rot); yp[i]=y0-(int) (y_rot); } g.drawPolygon(xp,yp,N); //多角形を描画 ② } } ヒント 点線枠②では、 「青色で三角形を塗りつぶし、その後に黒線で三角形(の輪郭)を 描く」という処理を行えば良いのです。多角形の塗りつぶしは「プログラミング」テキ スト p.209 の fillPolygon(x,y,N)メソッドを用います。 66
© Copyright 2024 ExpyDoc