練習問題
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.sin,Math.cosメソッドを利用しましょう.
ただし,以下の点に注意してください.
- 引数にはラジアンの値を渡してください.
-
$\pi$を利用するには,
Math.PIという変数を利用してください. - すなわち,$\sin \frac{\pi}{3}, \cos \frac{\pi}{3}$を Java で求めるには,次のようなコードを用いてください.
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としてください.
コッホ曲線の例を以下に示します(画像のクリックで画像が更新されます).
- $l=(\sqrt{(x_5 - x_1)^2 + (y_5 - y_1)^2})/3$
- $(x_2, y_2) = (x_1 + l, y_1)$
- $(x_3, y_3) = (x_2 + l\cos{\frac{\pi}{3}}, y_2 + l\sin{\frac{\pi}{3}})$
- $(x_4, y_4) = (x_1 + 2l, y_1)$
- $l=(\sqrt{(x_5 - x_1)^2 + (y_5 - y_1)^2})/3$
- $(x_2, y_2) = (x_1 + l\cos{\theta}, y_1 + l\sin{\theta})$
- $(x_3, y_3) = (x_2 + l\cos{(\theta + \frac{\pi}{3})}, y_2 + l\sin{(\theta + \frac{\pi}{3})})$
- $(x_4, y_4) = (x_3 + l\cos{(\theta + \frac{\pi}{3} - \frac{2\pi}{3})}, y_3 + l\sin{(\theta + \frac{\pi}{3} - \frac{2\pi}{3})}) = (x_3 + l\cos{(\theta - \frac{\pi}{3})}, y_3 + l\sin{(\theta - \frac{\pi}{3})})$
この計算式で,コッホ曲線を描いてみましょう. 再帰呼び出しを利用すると良いでしょう. $(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,000ミリ秒(1秒))スリープする.
- ただし,何秒かに一回程度,描画されない秒が出てくる.
- 針の両端座標の計算処理の積み重ねのため.
- これを防ぐためには,スリープの秒数を少なくする.
- ただし,そのぶん処理が重くなり,チラツキの原因となる.
- これらの問題は,ここでは解決する必要はない.
- 全ての描画をクリアする.
- 1に戻る.
度数法から弧度法(ラジアン)に変更する
Math.toRadiansに度数法の値(0〜360度)を渡せばラジアン値が得られる.
Double degree = // 度数法による角度
Double radian = Math.toRadians(degree); // 弧度法による角度針の両端座標の計算
- 中心座標は常に同じ.もう一方の端を毎秒,計算により求める.
- 秒針は
degreeOfSeconds = date.getSeconds() * 6.0 - 90で得られる角度を元に計算する. - 長針も秒針と同様.
date.getSeconds()の代わりにdate.getMinutes()を利用する. - 短針は,
degreeOfHours = (date.getHours() * 5 + date.getMinutes() / 12.0) * 6.0 - 90で値を得る.date.getHours() * 30 - 90で計算すると,例えば,6:30 の時でも短針は一番下を指したままである. そうではなく,長針が進むに従って,短針も少しずつ移動して欲しいため,上記の処理としている.
再描画
EZ.refreshScreen() を呼び出すと,今まで追加した要素を再描画します.
つまり,これまでに addLineやaddCircleなどで追加した図形を再描画します.
ここでは,1秒ごとに新たな線を引きたいため,今まで追加した図形を削除する必要があります.
そのために,EZ.refreshScreen()ではなく,EZ.removeAllEZElements()を呼び出す必要があります.
もちろん,追加した EZLine の実体に対して,適切に座標を変更した上で,EZ.refreshScreen()を呼び出せば期待通りの動作となります.
