07 年 CG エンジニア検定 CG 部門 1 級一次試験 ( 記述式 ) 解答 第 1 問 正解答 a.90 b.(2, 0, ) c.(0, 0, -6) d.(-2, 0, -9) e.6 第 2 問 正解答 a.0 b.1 c. 1 ] t 6 t 4 6-2 + g d. 1 2 1 P + P + P 6 6 0 1 2 e. 1 2 1 P + P + P 6 6 1 2 f. 1 ] t 2-4 t g 2 g. 1 ^ P P 0 2 2- h h. 1 ^ 2P 1+ P 2h i. 1 ^ P 1+ 2 P 2h
第 問 正解答 a. I ] r g= k ] r g I ] r gcos a= 0 d d i N $ L 4 2 10 I d ^gh= k d ^gh I i ^gh cos a= 0. 4# 10# = 4# = = N L 5 18 5 5 I ] bg= k ] bg I ] bgcos a= 0 d d i b. 1 15 2 ^7, -, 1h c. ^7, -, 1h $ ^1, -2, h 7 40 50 cos c = = + + = = 15 2 1+ 4+ 9 0 7 0 7 5 7 4 d. 4 5 625 625 I s= k s I i cos c= 0. # 10# d n = # = 7 969 12 第 4 問 (1) y (2) ^-a, ah ^a, ah ^-a, ah y ^a, ah E S E x x S ^-a, -ah ^a, -ah ^-a, -ah ^a, -ah () y (4) ^-a, ah ^a, ah ^-a, ah y ^a, ah S E x E S x ^-a, -ah ^a, -ah ^-a, -ah ^a, -ah
第 5 問 正解答 C 言語 Java 共通 a.vol_y b.(k-vol_x/2.0)*(k-vol_x/2.0)+(j-vol_y/2.0)*(j-vol_y/2.0) c.vol_z d.volume[k][j][i] e.mip[k][j]
07 年 CG エンジニア検定 CG 部門 1 級一次試験 ( 論述式 ) 解答 第 1 問 正解答例 a. 12 14 25 16 18 22 17 15 17 24 1 15 b. バイリニア補間式 : f ^ x, yh= 22-8x- 6y+ 12xy 判別式 :D=-12 等高線 : 16 22 14 c.d=0 を式 に代入すれば, 直ちに c2 c1 d x+ n d y+ n= 0 c c c2 c1 を得る. したがって,x + = 0もしくは y+ = 0. すなわち, その等高線はスクエアを4 分割する縦横 2 本 c c の漸近線自身になる. d. 漸近線同士の交点および漸近線とスクエアの辺との交点の符号を考慮すれば, 図 のいずれの場合も,4 つのサブスクエアはパターン0,1,,4のいずれかになっていることがわかる. そのままでは複雑で分類しきれないスクエアを細分することによって, より単純な既知のケースに帰着させていることから, この手法は, 分割統治法の原理に基づいているということができる.
第 2 問 正解答例 a. もともと 2 次元の画像を 次元に拡張した 次元画像, すなわちボリュームデータの形式が適している. 具 体的にはボクセル表現やオクトリー表現などである. b. 等値面 ( アイソサーフェス ) 抽出処理を行えばよい. 具体的には, マーチングキューブ法などのアルゴリズム を用いて, 臓器と空洞部分, 臓器どうし, あるいは骨と筋肉などの境界面を求め, 細かいポリゴンで表面を近 似したモデルに変換する. c. 例 1. 注釈表示 ( アノテーション ) 機能 各臓器 筋肉 骨の名称を, 引き出し線も付けて CG 画像に上書きし表示する必要がある. 拡大縮小操作 の影響を受けず画面上で一定の大きさで文字列を表示する. また, 回転操作の影響も受けず常にユーザ の側を向くように表示する必要もある. 2. 半透明表示 非表示制御機能 人体の内部は多くの器官が重なり合っているため, 任意の器官を選択的に半透明表示したり非表示にし たりする機能をもつことが望ましい.. 断面表示機能 各器官の形状を把握しやすくするため, 断面を表示し, 断面位置をマウス操作で連続的に移動できるこ とが必要である. 少なくとも垂直 水平 奥行きの 方向の断面設定機能が必要である. また, ユーザイ ンタフェースを工夫して任意方向の断面をとる機能があることも望ましい. 4. その他 たとえば, 立体視表示 (D 表示 ) 機能, 拡大縮小時の LOD 機能, など. d. 例 1 つは, 特殊なハードウェア装置が必要かどうかを確認する必要がある. たとえば, マウスで操作する PC だ けでよいのか, メスに見立てた特殊な 次元入力装置が必要なのか, 表示装置として VR で使うような没入感 のある大画面表示装置が必要なのか, などである. 2 つ目には, ソフトウェアの機能として, 元の断層画像データを取り込むかどうかを確認する必要がある. 一般的な訓練のためなら不要だが, 毎回の手術対象患者のデータを取り込むには前処理部をユーザ用に改変 する必要があるため, 大幅な追加開発が発生する. そのほか, メスで患部を開く機能でどの程度リアルに変形を行うか, 操作中に血管とメスとの干渉チェッ クを行うかどうか, などがポイントとなりうる.
第 問 正解答例 C 言語の場合 int projection(vector v0[], Vector v1[]) /* v0[0], v0[1], v0[2] T0 の頂点 */ /* v1[0], v1[1], v1[2] T1 の頂点 */ { Vector w0[2]; /* T0 の2 辺を表すベクトル */ Vector w1[2]; /* T1 の2 辺を表すベクトル */ Vector lgt; /* 平行光の方向ベクトル */ int flag; /* 判定値 ; 内部なら 1, さもなければ0 */ int i; /* ループカウンタ ; i = 0,1,2 */ Matrix M0, M1; /* x 行列, およびその逆行列 */ Vector c0; /* 方程式の定数項ベクトル */ double t0, t1, t2; /* 方程式の 変数 */ Vector tv; /* t0,t1,t2 を要素とするベクトル */ Vector v2[]; /* T2 の頂点 v2[0],v2[1],v2[2] */ /* T0 の2 辺を表すベクトルw0[0], w0[1] を求め, */ /* 平行光の方向ベクトル lgt を求める */ w0[0] = subtract(v0[1], v0[0]); w0[1] = subtract(v0[2], v0[0]); lgt = crossproduct(w0[0], w0[1]); /* T1 の2 辺を表すベクトルw1[0], w1[1] を求める */ w1[0] = subtract(v1[1], v1[0]); w1[1] = subtract(v1[2], v1[0]); /* T0 の つの頂点 v0[0],v0[1],v0[2] に対して同じ処理を行う */ flag = 1; /* 判定値 flag に初期値 1 を与えておく */ for (i = 0; i < ; i++) { /* t0,t1,t2 を つの変数とする下記の方程式を解く : */ /* v0[i] + t0 * lgt = v1[0] + t1 * w1[0] + t2 * w1[1] */ /* x 行列 M0, 定数項 c0 を用いると, 方程式は下記のように書ける : */ /* [t0 t1 t2] * [M0] = [c0.x c0.y c0.z] */ M0 = setmatrix(-lgt.x, -lgt.y, -lgt.z, w1[0].x, w1[0].y, w1[0].z, w1[1].x, w1[1].y, w1[1].z); c0 = subtract(v0[i], v1[0]); /* M0 の逆行列をM1 とすると, t0,t1,t2 は以下のように求められる : */ /* [t0 t1 t2] = [c0.x c0.y c0.z] * [M1] */ M1 = invert(m0); tv = mulvecmat(c0, M1); t0 = tv.x; t1 = tv.y; t2 = tv.z; /* T2 の頂点 v2[i] を求める */ v2[i] = addsclmul(v0[i], t0, lgt);
/* t1,t2 がいずれも0 または正で, なおかつ t1+t2 が1 以下ならば, */ /* v2[i] はT1 の内部に完全に含まれる. これらの条件がひとつでも */ /* 成立しない場合は, 判定値 flag を0 にする */ if (t1 < 0.0) { else if (t2 < 0.0) { else if (t1 + t2 > 1.0) { /* T2 を描画する */ drawtriangle(v2[0], v2[1], v2[2]); /* 判定結果を返す */ return flag; Java の場合 public static int projection(vector[] v0, Vector[] v1) /* v0[0], v0[1], v0[2] T0 の頂点 */ /* v1[0], v1[1], v1[2] T1 の頂点 */ { Vector[] w0 = new Vector[2]; /* T0 の2 辺を表すベクトル */ Vector[] w1 = new Vector[2]; /* T1 の2 辺を表すベクトル */ Vector lgt; /* 平行光の方向ベクトル */ int flag; /* 判定値 ; 内部なら 1, さもなければ0 */ int i; /* ループカウンタ ; i = 0,1,2 */ Matrix M0; /* x 行列 */ Matrix M1; /* M0 の逆行列 */ Vector c0; /* 方程式の定数項ベクトル */ double t0, t1, t2; /* 方程式の 変数 */ Vector tv; /* t0,t1,t2 を要素とするベクトル */ Vector[] v2 = new Vector[]; /* T2 の頂点 v2[0],v2[1],v2[2] */ /* T0 の2 辺を表すベクトルw0[0], w0[1] を求め, */ /* 平行光の方向ベクトル lgt を求める */ w0[0] = subtract(v0[1], v0[0]); w0[1] = subtract(v0[2], v0[0]); lgt = crossproduct(w0[0], w0[1]); /* T1 の2 辺を表すベクトルw1[0], w1[1] を求める */ w1[0] = subtract(v1[1], v1[0]); w1[1] = subtract(v1[2], v1[0]);
/* T0 の つの頂点 v0[0],v0[1],v0[2] に対して同じ処理を行う */ flag = 1; /* 判定値 flag に初期値 1 を与えておく */ for (i = 0; i < ; i++) { /* t0,t1,t2 を つの変数とする下記の方程式を解く : */ /* v0[i] + t0 * lgt = v1[0] + t1 * w1[0] + t2 * w1[1] */ /* x 行列 M0, 定数項 c0 を用いると, 方程式は下記のように書ける : */ /* [t0 t1 t2] * [M0] = [c0.x c0.y c0.z] */ M0 = setmatrix(-lgt.x, -lgt.y, -lgt.z, w1[0].x, w1[0].y, w1[0].z, w1[1].x, w1[1].y, w1[1].z); c0 = subtract(v0[i], v1[0]); /* M0 の逆行列をM1 とすると, t0,t1,t2 は以下のように求められる : */ /* [t0 t1 t2] = [c0.x c0.y c0.z] * [M1] */ M1 = invert(m0); tv = mulvecmat(c0, M1); t0 = tv.x; t1 = tv.y; t2 = tv.z; /* T2 の頂点 v2[i] を求める */ v2[i] = addsclmul(v0[i], t0, lgt); /* t1,t2 がいずれも0 または正で, なおかつ t1+t2 が1 以下ならば, */ /* v2[i] はT1 の内部に完全に含まれる. これらの条件がひとつでも */ /* 成立しない場合は, 判定値 flag を0 にする */ if (t1 < 0.0) { else if (t2 < 0.0) { else if (t1 + t2 > 1.0) { /* T2 を描画する */ drawtriangle(v2[0], v2[1], v2[2]); /* 判定結果を返す */ return flag;