練習問題

1. 図形の描画

次の図になるようにプログラムを作成してみましょう. 色は必ずしもこの通りでなくて構いません. プログラム名は,DrawShapes2としてください.

図形の描画の完成形

2. サイン波の描画

$0 \leq x \leq 2\pi$ の範囲でサイン波を描画してみましょう.クラス名は SineCurve としてください.

サイン波

ヒント

プログラム全体の構成

上の図は,399 本の直線で描画されています. x=0から400未満まで繰り返し,v = Math.sin(i * delta) * s で$(x_i, y_i)=(i, v)$を得ます. $((x_{i-1}, y_{i-1}), (x_i, y_i))$に線を追加することで上記のサイン波が描画できます.

なお,delta($\delta$)は横幅,s($s$)は高さを表しています. EZ.initialize(400, 400) で初期化した時, delta が $\delta = \frac{2\pi}{400}$,sは 150としてください($-1 \leq \sin\theta \leq 1$であり,この値を -150〜150に割り当てるため). また,中央に寄せるため,y 軸方向に +200 としてください.

Java での $sin$,$cos$

Java で,$\sin$, $\cos$を計算するには,Math.sinMath.cosメソッドを利用しましょう. ただし,以下の点に注意してください.

Double sinValue = Math.sin(Math.PI / 3.0);
Double cosValue = Math.cos(Math.PI / 3.0);

Double 型の Integer 型への変換

Double型をInteger型として扱うには,Double型の変数に対して,intValueメソッドを呼び出しましょう. 例えば,Double型のdValueという値を Integer型のiValueに代入するには,次のようなプログラムになります.

Double dValue = // Double型の値を代入.
Integer iValue = dValue.intValue();

3. コッホ曲線(Koch curve)の描画

コッホ曲線は,線分を三等分し,分割点を頂点とした正三角形を描く線です. この作図を無限に繰り返すことで,線分の長さが$\infty$になります. コマンドライン引数でコッホ曲線の $n$ を指定できるようにしましょう.

クラス名は,KochCurveとしてください. コッホ曲線の例を以下に示します(画像のクリックで画像が更新されます).

コッホ曲線

上記のように,$(x_1, y_1)$と$(x_5, y_5)$が指定された時,$(x_2, y_2)$〜$(x_4, y_4)$を求めましょう.

$n=1$までは上記のように計算できますが,$n>2$の場合はこの計算では求められません. 次の例を元に考えてみましょう(画像のクリックで画像が更新されます).

上記のように,$(x_1, y_1)$と$(x_5, y_5)$が指定された時,$(x_2, y_2)$〜$(x_4, y_4)$を求めましょう. 元々の傾きを$\theta$として示します.

この計算式で,コッホ曲線を描いてみましょう. 再帰呼び出しを利用すると良いでしょう. $(x_2, y_2),(x_3, y_3)$間の直線を引く時,また,$(x_3, y_3),(x_4, y_4)$間の直線を引く時に それぞれを$(x_1, y_1),(x_5, y_5)$として再帰呼び出しを行えばコッホ曲線を描けるでしょう.

ヒント

再帰呼び出し

次のようなメソッドを用意しましょう.このメソッドを呼び出すことで,2点の間にコッホ曲線を描けるようになります.

void drawKoch(Integer x1, Integer y1, Integer x5, Integer y5,
      Integer dimension, Double angle){

  if(dimension == 0){
    // (x1, y1)から(x5, y5)まで線を引く.
  }
  else{
    // (x1, y1), (x5, y5) 間の長さの 1/3.これが l となる.
    Double length = // 長さlを求める.
    Double delta = Math.PI / 3.0;

    // (x2, y2) を求める.
    // (x1, y1)から(x2, y2)まで線を引く.

    // (x3, y3) を求める(θ は angle + delta).
    // (x2, y2)から(x3, y3)まで線を引く.
    this.drawKoch(x2.intValue(), y2.intValue(),
                  x3.intValue(), y3.intValue(),
                  dimension - 1, angle + delta);

    // (x4, y4) を求める(θ は angle - delta).
    // (x3, y3)から(x4, y4)まで線を引く.
    this.drawKoch(x3.intValue(), y3.intValue(),
                  x4.intValue(), y4.intValue(),
                  dimension - 1, angle - delta);

    // (x4, y4)から(x5, y5)まで線を引く.
  }
}

実行例

コッホ曲線

画像のクリックで画像が更新されます.

4. コッホ曲線(Koch curve)のアニメーション描画

コッホ曲線を$n=0$から$n=5$までを 1 秒程度で更新して描いてみましょう. クラス名は,KochCurveAnimationとしてください.

今まで描画した内容を消したい場合は,EZ.removeAllEZElements() メソッドを呼び出してください.

5. 斜方投射

例題 3例題 4を合わせた動きをするボールを描きましょう. $x$軸方向には,例題3を,$y$軸方向には,例題4の動きを設定すれば良いでしょう. クラス名を ThrowingExercise にしてください.

実行例

斜方投射の実行例

6. アニメーション

EZ Graphics を利用して,自由にアニメーションを描いてください. クラス名は Animation としてください. 内容は自由です.

7. アナログ時計

EZ.javaを利用して,アナログ時計を描画してください. クラス名は Clockとします.

実行例

アナログ時計

この時の時刻は,19時22分25秒.

ヒント

基本的な描画方法

  1. 現在時刻を取得する.
  2. 背景を描画する.
  3. 短針,長針,秒針の両端座標を計算で求める.
  4. 短針,長針,秒針をそれぞれ描画する.
  5. 適当な時間(1,000ミリ秒(1秒))スリープする.
    • ただし,何秒かに一回程度,描画されない秒が出てくる.
    • 針の両端座標の計算処理の積み重ねのため.
    • これを防ぐためには,スリープの秒数を少なくする.
    • ただし,そのぶん処理が重くなり,チラツキの原因となる.
    • これらの問題は,ここでは解決する必要はない.
  6. 全ての描画をクリアする.
  7. 1に戻る.
秒のスキップ,チラツキの両方を解決したい場合は,以下のことを試してみること.

度数法から弧度法(ラジアン)に変更する

Double degree = // 度数法による角度
Double radian = Math.toRadians(degree); // 弧度法による角度

針の両端座標の計算

なぜ-90度なのか

再描画

EZ.refreshScreen() を呼び出すと,今まで追加した要素を再描画します. つまり,これまでに addLineaddCircleなどで追加した図形を再描画します. ここでは,1秒ごとに新たな線を引きたいため,今まで追加した図形を削除する必要があります. そのために,EZ.refreshScreen()ではなく,EZ.removeAllEZElements()を呼び出す必要があります.

もちろん,追加した EZLine の実体に対して,適切に座標を変更した上で,EZ.refreshScreen()を呼び出せば期待通りの動作となります.

参考