東京理科大学 infoserv[更新日]2001.4.20


次の問9から問11までの3問については,この中から1問を選択し, 答案用紙の選択欄の を マークして解答してください。 なお,2問以上選択した場合には,はじめの1問について採点します。

問9

 次の C プログラムの説明及びプログラムを読んで,設問 1 〜 4 に答えよ。

〔プログラムの説明〕

画面上の点 S の座標 (sx, sy) と点 E の座標 (ex, ey) を両端とする自由曲線を, 微細な直線群で近似して描く関数 DrawCurve を作成した。 自由曲線の形を決めるために,二つの制御点 C1 の座標 (x1, y1) と C2 の 座標 (x2, y2) を引数で指定する。 図のように与えられた 4 点で構成される折れ線を再帰的に分割していき, 引数 len (len > 2) によって定まる収束条件が成立した時点で直線を描画する。


(● は,点の座標を表すための記号であって描画形状ではない)
図 与えられた 4 点の座標

関数 DrawCurve の原型(プロトタイプ)は,

void DrawCurve( int sx, int sy, int x1, int y1, int x2, int y2, int ex, int ey, int len ) ;

であり,引数と点の座標の関係は,図のとおりである。

ここで,2 点を結ぶ直線を描画するために次の二つの関数が用意されている。


void MoveTo( int sx, int sy ) ;
機能:直線を描画する始点を座標 (sx, sy) とする。


void LineTo( int ex, int ey ) ;
機能:現在の始点から,座標 (ex, ey) まで直線を描き,始点を座標 (ex, ey) に更新する。

〔プログラム〕

void    MoveTo( int sx, int sy ) ;
void    LineTo( int ex, int ey ) ;
int     CmpLine( int xs, int ys, int xe, int ye, int len ) ;
void  DrawCurve( int sx, int sy, int x1, int y1, int x2, int y2,
                 int ex, int ey, int len )
{
  int   p1x, p1y, p2x, p2y, p3x, p3y ;
  int   p4x, p4y, p5x, p5y, p6x, p6y ;
  if ( CmpLine( sx, sy, x1, y1, len ) && 
       CmpLine( x1, y1, x2, y2, len ) &&
       CmpLine( x2, y2, ex, ey, len )  )  {
        MoveTo( sx, sy ) ; LineTo( x1, y1 ) ;
        LineTo( x2, y2 ) ; LineTo( ex, ey ) ;
        return ;
  }
  p1x = ( sx + x1 ) / 2 ; p1y = ( sy + y1 ) / 2 ;
  p2x = ( x1 + x2 ) / 2 ; p2y = ( y1 + y2 ) / 2 ;
  p3x = ( x2 + ex ) / 2 ; p3y = ( y2 + ey ) / 2 ;
  p4x = ( p1x + p2x ) / 2 ; p4y = ( p1y + p2y ) / 2 ; 
  p5x = ( p2x + p3x ) / 2 ; p5y = ( p2y + p3y ) / 2 ;
  p6x = ( p4x + p5x ) / 2 ; p6y = ( p4y + p5y ) / 2 ;
  DrawCurve( sx, sy, p1x, p1y, p4x, p4y, p6x, p6y, len ) ;
  DrawCurve( p6x, p6y, p5x, p5y, p3x, p3y, ex, ey, len ) ;
  return ;
}
int  CmpLine( int xs, int ys, int xe, int ye, int len )
{
  int   len1 = xe - xs ;
  int   len2 = ye - ys ;
  if ( len1 < 0 ) len1 = -len1 ;
  if ( len2 < 0 ) len2 = -len2 ;
  if ( ( len1 < len ) && ( len2 < len ) )
        return  1 ;
  return 0 ;
}

設問1  このプログラムでは,折れ線を二つに分割するため, 三つの線分の中点の座標を求めて,さらにいくつかの線分の中点の座標を求める。 新たな折れ線の四つの頂点を決定する方法を説明した図はどれか,解答群の中から選べ。

解答群

ア                  イ
  

ウ                  エ
  


設問2  再帰的な分割処理が終了する条件として, 正しいものを解答群の中から選べ。

解答群

ア 折れ線の三つの線分それぞれが,引数 len で与えられた長さより長くなった。

イ 折れ線の三つの線分それぞれが,引数 len で与えられた長さより短くなった。

ウ 折れ線の三つの線分それぞれが,引数 len を 1 辺とする正方形の中に含まれる長さになった。

エ 折れ線の三つの線分のうち,どれか 1 本が,引数 len で与えられた長さより長くなった。

オ 折れ線の三つの線分のうち,どれか 1 本が,引数 len で与えられた長さより短くなった。

カ 折れ線の三つの線分のうち,どれか 1 本が,引数 len を 1 辺とする正方形の中に含まれる長さになった。


設問3  このプログラムの特性を説明する次の記述中の に入れる正しい答えを,解答群の中から選べ。

引数 len の値を 8 にして自由曲線を描画した場合, 直線を描画する関数 LineTo の呼出し回数が最も多かった曲線は である。

同じ曲線を引数 len の値を 16 にして描画した場合, 引数 len の値が 8 のときと比較して,関数 LineTo の呼出し回数は

a に関する解答群

     ア                   イ 

     ウ                   エ

b に関する解答群

ア 多くなる    イ 変わらない    ウ 少なくなる


設問4 次のプログラムの実行結果として正しい図を,解答群の中から選べ。

int Lines ;
int cx1, cy1 ;
int cx2, cy2 ;
for ( Lines = 0, cx1 = 128, cy1 = 160, cx2 = 256, cy2 = 160 ;
       Lines < 16 ;
       Lines++,  cx1 += 16, cy1 -= 16, cx2 -= 16, cy2 += 16 ) {
        DrawCurve( 50, 160, cx1, cy1, cx2, cy2, 384, 160, 8 ) ;
}

解答群

     ア               イ 

     ウ               エ 


東京理科大学 infoserv 戻る 次頁:問10