MMPAINT.C

[目次 | 関数]

目次

関数一覧


   1|/***************************************************************************
   2|*  1. <<< ポリゴン塗りつぶし (MMPaint) >>> 
   3|****************************************************************************/
   4|
   5|#include  <all.h>
   6|
   7|#ifndef USES_TYPEX
   8|#error  need TYPEX
   9|#endif
  10|
  11|/*************************************************************************
  12|*  2. <<< 初期化する [MMPaint_init()] >>>
  13|*【引数】
  14|*  ・int*  mmBuf;  最大最小値を格納するバッファ配列、要素数は height*2
  15|*【補足】
  16|*・height には、塗りつぶす可能性がある最大の Y座標 + 1 を指定します。
  17|*  つまり、塗りつぶす Y座標の範囲は 0〜(height-1) になります。
  18|*・X 座標の範囲はありません。
  19|**************************************************************************/
  20|void  MMPaint_init( MMPaint* m, int* mmBuf, size_t mmBuf_sizeof,
  21|  int height )
  22|{
  23|  #ifdef _CHECKER
  24|    if ( mmBuf_sizeof < sizeof(int) * height * 2 )  error();
  25|  #endif
  26|
  27|  m->xmin = &mmBuf[0];
  28|  m->xmax = &mmBuf[height];
  29|  m->height = height;
  30|}
  31|
  32|
  33|/*************************************************************************
  34|*  3. <<< ポリゴンの情報をクリアする [MMPaint_clear()] >>>
  35|**************************************************************************/
  36|void  MMPaint_clear( MMPaint* m )
  37|{
  38|  int  i;
  39|
  40|  for ( i = 0; i < m->height; i++ ) {
  41|    m->xmin[i] = INT_MAX;
  42|    m->xmax[i] = (int)INT_MIN;
  43|  }
  44|  m->ymin = INT_MAX;
  45|  m->ymax = (int)INT_MIN;
  46|}
  47|
  48|
  49|/*************************************************************************
  50|*  4. <<< ポリゴンの辺を設定する [MMPaint_setBound()] >>>
  51|*【機能】
  52|*・点(x1,y1)と点(x2,y2)をむすぶ線分をポリゴンの辺の1つに設定します。
  53|*【補足】
  54|*・各 Y 座標における X 座標の最小値と最大値を次のようにチェックします。
  55|*  
  56|**************************************************************************/
  57|void  MMPaint_setBound( MMPaint* m, int x1, int y1, int x2, int y2 )
  58|{
  59|  /* Y 座標の有効範囲(0〜height-1)からはみ出たとき、クリッピングする */
  60|  if ( y1 < 0 ) {
  61|    if ( y2 < 0 )  return;
  62|    x1 = (0 - y2) * (x1 - x2) / (y1 - y2) + x2;
  63|    y1 = 0;
  64|  }
  65|  if ( y2 < 0 ) {
  66|    x2 = (0 - y1) * (x2 - x1) / (y2 - y1) + x1;
  67|    y2 = 0;
  68|  }
  69|  if ( y1 >= m->height ) {
  70|    if ( y2 >= m->height )  return;
  71|    x1 = ((m->height - 1) - y2) * (x1 - x2) / (y1 - y2) + x2;
  72|    y1 = m->height - 1;
  73|  }
  74|  if ( y2 >= m->height ) {
  75|    x2 = ((m->height - 1) - y1) * (x2 - x1) / (y2 - y1) + x1;
  76|    y2 = m->height - 1;
  77|  }
  78|
  79|  /* ymin と ymax をチェックする */
  80|  if ( y1 < m->ymin )  m->ymin = y1;
  81|  if ( y1 > m->ymax )  m->ymax = y1;
  82|  if ( y2 < m->ymin )  m->ymin = y2;
  83|  if ( y2 > m->ymax )  m->ymax = y2;
  84|
  85|  /* xmin, xmax をチェックする */
  86|  {
  87|    int  x,y,n;
  88|    int  dx, dy;
  89|    int  cup;           /* カウンタ */
  90|    int  plus, minus;   /* カウンタの増分、減分 */
  91|    int  flag;          /* cup による座標の増減, +1 or -1 */
  92|
  93|    /* 90度〜270度(左向き)の場合 */
  94|    if ( x1 > x2 ) {
  95|      n = x1; x1 = x2; x2 = n;
  96|      n = y1; y1 = y2; y2 = n;
  97|    }
  98|
  99|    /* dx, dy, flag の設定 */
 100|    dx = x2 - x1;
 101|    dy = y2 - y1;
 102|    if ( dy > 0 )
 103|      flag = +1;
 104|    else {
 105|      flag = -1;  dy = -dy;
 106|    }
 107|
 108|    /* 0度〜45度(水平より右下がり)の場合 */
 109|    /* 0度〜-45度(水平より右上がり)の場合 */
 110|    if ( dx >= dy ) {
 111|      plus = 2 * dy;    /* plus = 2dy */
 112|      cup = plus - dx;  /* (dy % dx) * 2 */
 113|      minus = cup - dx; /* minus = -2dx */
 114|
 115|      if ( x1 < m->xmin[y1] )  m->xmin[y1] = x1;  /* 点 */
 116|      y = y1;
 117|      for ( x = x1 + 1; x <= x2; x++ ) {
 118|        if ( cup > 0 ) {
 119|          if ( x-1 > m->xmax[y] )  m->xmax[y] = x-1;  /* 点 */
 120|          y += flag;
 121|          if ( x < m->xmin[y] )  m->xmin[y] = x;  /* 点 */
 122|          cup += minus;
 123|        }
 124|        else
 125|          cup += plus;
 126|      }
 127|      x--;
 128|      if ( x > m->xmax[y] )  m->xmax[y] = x;  /* 点 */
 129|    }
 130|
 131|    /* 45度〜90度(垂直より右下がり)の場合 */
 132|    /* -45度〜-90度(垂直より右上がり)の場合 */
 133|    else {
 134|      if ( flag < 0 ) {
 135|        n = x1; x1 = x2; x2 = n;
 136|        n = y1; y1 = y2; y2 = n;
 137|      }
 138|      plus = 2 * dx;
 139|      cup = plus - dy;
 140|      minus = cup - dy;
 141|
 142|      if ( x1 < m->xmin[y1] )  m->xmin[y1] = x1;  /* 点 */
 143|      if ( x1 > m->xmax[y1] )  m->xmax[y1] = x1;  /* 点 */
 144|      x = x1;
 145|      for ( y = y1 + 1; y <= y2; y ++ ) {
 146|        if ( cup > 0 )
 147|          { x += flag;  cup += minus; }
 148|        else
 149|          cup += plus;
 150|
 151|        if ( x < m->xmin[y] )  m->xmin[y] = x;  /* 点 */
 152|        if ( x > m->xmax[y] )  m->xmax[y] = x;  /* 点 */
 153|      }
 154|    }
 155|  }
 156|}
 157| 
 158|