twod.c

C:\home\SVGCats_src\src\twod.c

[目次 | 関数]

目次

関数一覧


   1|/**************************************************************************
   2|*  1. <<< 二次元グラフィックス(代数)(TwoD) >>> 
   3|***************************************************************************/
   4|
   5|#include <math.h>
   6|#ifdef  USES_MXP_AUTOINC
   7| #include "twod.ah"  /* Auto include header, Look at mixer-... folder */
   8|#else
   9| #include  <all.h>
  10|#endif
  11|
  12|
  13| 
  14|/*-------------------------------------------------------------------------*/
  15|/* 2. <<< ◆二次元座標 (TwoD_XY) >>> 
  16|/*-------------------------------------------------------------------------*/
  17|
  18|
  19| 
  20|/*************************************************************************
  21|*  3. <<< [TwoD_XY_rot] 回転する >>> 
  22|*【引数】
  23|*  ・TwoD_XY*  center;  回転する座標(入出力)
  24|*  ・TwoD_XY*  center;  回転の中心座標
  25|*  ・double    radian;  角度(左回り、ラジアン、座標系に注意)
  26|*【補足】
  27|*・radian は、X 軸の右向きが Y 軸(一般のグラフィック画面)の場合のものです。
  28|*  左向きに Y 軸がある場合、マイナスの radian を指定します。
  29|**************************************************************************/
  30|void  TwoD_XY_rot( TwoD_XY* m, const TwoD_XY* center, double radian )
  31|{
  32|  double  x;
  33|
  34|  ERRORS_FUNC_START( TwoD_XY_rot );
  35|
  36|  m->x -= center->x;  m->y -= center->y;
  37|
  38|  x = m->x;
  39|  m->x =  x * cos(radian) - m->y * sin(radian);
  40|  m->y =  x * sin(radian) + m->y * cos(radian);
  41|
  42|  m->x += center->x;  m->y += center->y;
  43|
  44|  ERRORS_FUNC_END( TwoD_XY_rot );
  45|}
  46|
  47| 
  48|#ifdef USES_THREED
  49|/*************************************************************************
  50|*  4. <<< [TwoD_XY_initBy3D] 三次元座標から二次元座標を初期化する >>> 
  51|*【補足】
  52|*・p の座標系は、ThreeD_TwoD_initByP3 関数で f を初期化したときのものと
  53|*  同じ座標系にしてください。
  54|**************************************************************************/
  55|void  TwoD_XY_initBy3D( TwoD_XY* m, ThreeD_TwoD* f, ThreeD_XYZ* p )
  56|{
  57|  ERRORS_FUNC_START( TwoD_XY_initBy3D );
  58|
  59|  m->x = ThreeD_Vect_getDirLen( (ThreeD_Vect*)p, &f->x_coord );
  60|  m->y = ThreeD_Vect_getDirLen( (ThreeD_Vect*)p, &f->y_coord );
  61|
  62|  ERRORS_FUNC_END( TwoD_XY_initBy3D );
  63|}
  64|#endif /* USES_THREED */
  65|
  66|
  67| 
  68|/*************************************************************************
  69|*  5. <<< [TwoD_XY_getCrossLineH] 水平線と線分の交点座標を格納する >>> 
  70|*【引数】
  71|*  ・double  y;         水平線の Y 座標
  72|*  ・TwoD_XY*  p1, p2;  線分の両端の点
  73|*  ・TwoD_XY*  out;     交点座標
  74|*  ・int  返り値;       0=正常、1=線分と水平線は交わらない、
  75|*                       2=線分と水平線は平行
  76|*【補足】
  77|*・返り値が 1 の場合、out には、線分を直線とした交点座標を格納します。
  78|*・返り値が 2 の場合、out には、元の値が格納されたままになります。
  79|*・たとえば、次の図のように、指定した点を含む水平線(X 軸平行線)を考える際に、
  80|*  使用します。
  81|*  <IMG src="twod1.gif">
  82|*・水平線が線分に接する場合、線分の上端(Y小)なら交わる、線分の下端(Y大)なら
  83|*  交わらないと判定します。
  84|**************************************************************************/
  85|int  TwoD_XY_getCrossLineH( double y, TwoD_XY* p1, TwoD_XY* p2,
  86|  TwoD_XY* out )
  87|{
  88|  ERRORS_FUNC_START( TwoD_XY_getCrossLineH );
  89|
  90|  /* p1 の Y 座標が p2 の Y 座標より小さくする */
  91|  if ( p1->y > p2->y ) {
  92|    TwoD_XY*  s;    s = p1;  p1 = p2;  p2 = s;
  93|  }
  94|
  95|  /* 交点座標を格納する */
  96|  if ( p1->y == p2->y )  return  2;
  97|  out->x = (p1->x * (p2->y - y) + p2->x * (y - p1->y)) / (p2->y - p1->y);
  98|  out->y = y;
  99|
 100|  /* 線分と交わっているか判定する */
 101|  ERRORS_FUNC_END( TwoD_XY_getCrossLineH );
 102|
 103|  return  ( p1->y <= y && y < p2->y ) ? 0 : 1;
 104|}
 105|
 106|
 107| 
 108|/*************************************************************************
 109|*  6. <<< [TwoD_XY_isInPoly()] 点がポリゴンの内部にあるかどうか判定する >>> 
 110|*【補足】
 111|*・次の図のように、指定した点を含む水平線(X 軸平行線)を考えます。
 112|*  <IMG src="twod1.gif">
 113|**************************************************************************/
 114|bool  TwoD_XY_isInPoly( TwoD_XY* p, TwoD_Poly* poly )
 115|{
 116|  int  i,j;
 117|  int  count = 0;
 118|  TwoD_XY  cross;
 119|
 120|  ERRORS_FUNC_START( TwoD_XY_isInPoly );
 121|
 122|  /* 指定した点を含む水平線(X 軸平行線)とポリゴン辺との交点を考え、*/
 123|  /* X 座標が、指定した点より小さい交点の数を数える */
 124|  for ( i = 0; i < poly->n; i++ ) {
 125|    j = ( i + 1 ) % poly->n;
 126|    if ( TwoD_XY_getCrossLineH( p->y, &poly->p_array[i], &poly->p_array[j],
 127|         &cross ) == 0 ) {  /*★*/
 128|      if ( cross.x < p->x ) {
 129|        count ++;
 130|      }
 131|    }
 132|  }
 133|
 134|  ERRORS_FUNC_END( TwoD_XY_isInPoly );
 135|
 136|  return  count % 2;
 137|}
 138|
 139|
 140| 
 141|/*************************************************************************
 142|*  7. <<< [TwoD_XY_print] 属性を表示する >>> 
 143|**************************************************************************/
 144|#ifndef  ERRORS_CUT_DEBUG_TOOL
 145|void  TwoD_XY_print( TwoD_XY* m )
 146|{
 147|  Errors_printf( "TwoD_XY:(%lf, %lf)", m->x, m->y );
 148|}
 149|#endif
 150|
 151|
 152| 
 153|/*-------------------------------------------------------------------------*/
 154|/* 8. <<< ◆ポリゴン (TwoD_Poly) >>>                                          */ 
 155|/*-------------------------------------------------------------------------*/
 156|
 157|
 158| 
 159|/*************************************************************************
 160|*  9. <<< [TwoD_Poly_init()] 初期化する >>> 
 161|**************************************************************************/
 162|void  TwoD_Poly_init( TwoD_Poly* m, TwoD_XY* p_array, int n, int color )
 163|{
 164|  ERRORS_FUNC_START( TwoD_Poly_init );
 165|
 166|  m->p_array = p_array;
 167|  m->n = n;
 168|  m->color = color;
 169|
 170|  ERRORS_FUNC_END( TwoD_Poly_init );
 171|}
 172|
 173|
 174| 
 175|/*************************************************************************
 176|*  10. <<< [TwoD_Poly_getConvexType] 凸型かどうか、左回りかどうか >>> 
 177|*【引数】
 178|*  ・int  返り値;  以下の定数のうちどれか(向きと座標系に注意→補足)
 179|*        TwoD_LeftConvex, TwoD_RightConvex, TwoD_NotConvex, TwoD_NotPoly
 180|*【補足】
 181|*・返り値は、X 軸の右向きが Y 軸(一般のグラフィック画面)の場合のものです。
 182|*  X 軸の左向きが Y 軸の場合、右回りと左回りの判定が逆になります。
 183|**************************************************************************/
 184|int  TwoD_Poly_getConvexType( TwoD_Poly* m )
 185|{
 186|  int  ret;
 187|  TwoD_XY*  p1;
 188|  TwoD_XY*  p1_last2;
 189|  TwoD_XY*  p2;
 190|  TwoD_XY*  p3;
 191|  TwoD_XY   v1, v2;  /* ベクトル (v1=p2-p1, v2=p3-p2) */
 192|  int  nLeft = 0;    /* 左回転の回数 */
 193|  int  nRight = 0;   /* 右回転の回数 */
 194|  double  outProd;   /* 外積の値 */
 195|
 196|  ERRORS_FUNC_START( TwoD_Poly_getConvexType );
 197|
 198|  ASSERT( m->n >= 3 );
 199|
 200|  #if  ERRORS_DEBUG_FALSE
 201|    TwoD_Poly_print( m );
 202|  #endif
 203|
 204|  p1 = &m->p_array[0];
 205|  p2 = p1 + 1;
 206|  p3 = p2 + 1;
 207|  p1_last2 = p1 + m->n - 2;  /* 最後から2つ目の頂点 */
 208|
 209|  /* nLeft, nRight を数える(最後から3つ目の頂点まで)*/
 210|  v1.x = p2->x - p1->x;  v1.y = p2->y - p1->y;
 211|  for ( ; p1 < p1_last2;  p1++, p2++, p3++ ) {  /* 頂点数-2 */
 212|    v2.x = p3->x - p2->x;  v2.y = p3->y - p2->y;
 213|
 214|    outProd = TwoD_XY_getOutProd( &v1, &v2 );
 215|    if ( outProd < 0 )  nLeft ++;
 216|    else if ( outProd > 0 )  nRight ++;
 217|    #if  ERRORS_DEBUG_FALSE
 218|      Errors_printf( "nLeft = %d, nRight = %d", nLeft, nRight );
 219|    #endif
 220|
 221|    v1 = v2;
 222|  }
 223|
 224|  /* nLeft, nRight を数える(最後から2つ目の頂点)*/
 225|  p3 = &m->p_array[0];
 226|  v2.x = p3->x - p2->x;  v2.y = p3->y - p2->y;
 227|  outProd = TwoD_XY_getOutProd( &v1, &v2 );
 228|  if ( outProd < 0 )  nLeft ++;
 229|  else if ( outProd > 0 )  nRight ++;
 230|  v1 = v2;
 231|  #if  ERRORS_DEBUG_FALSE
 232|    Errors_printf( "nLeft = %d, nRight = %d", nLeft, nRight );
 233|  #endif
 234|
 235|  /* nLeft, nRight を数える(最後の頂点)*/
 236|  p1 = p3 + 1;
 237|  v2.x = p1->x - p3->x;  v2.y = p1->y - p3->y;
 238|  outProd = TwoD_XY_getOutProd( &v1, &v2 );
 239|  if ( outProd < 0 )  nLeft ++;
 240|  else if ( outProd > 0 )  nRight ++;
 241|  #if  ERRORS_DEBUG_FALSE
 242|    Errors_printf( "nLeft = %d, nRight = %d", nLeft, nRight );
 243|  #endif
 244|
 245|  /* 判定 */
 246|  if ( nLeft == 0 ) {
 247|    if ( nRight == 0 )  ret = TwoD_NotPoly;
 248|    else                ret = TwoD_RightConvex;
 249|  }
 250|  else {
 251|    if ( nRight == 0 ) ret = TwoD_LeftConvex;
 252|    else               ret = TwoD_NotConvex;
 253|  }
 254|
 255|  ERRORS_FUNC_END( TwoD_Poly_getConvexType );
 256|  return  ret;
 257|}
 258|
 259|
 260|
 261| 
 262|#ifdef USES_THREED
 263|/*************************************************************************
 264|*  11. <<< [TwoD_Poly_initByThreeD] 三次元ポリゴンから二次元ポリゴンを初期化する(1) >>> 
 265|*【機能】
 266|*・三次元ポリゴンをスクリーン座標に変換した二次元ポリゴンとして初期化します。
 267|*【引数】
 268|*  ・TwoD_XY*  p_array;   座標を格納するメモリ領域の先頭アドレス
 269|**************************************************************************/
 270|void  TwoD_Poly_initByThreeD( TwoD_Poly* m, TwoD_XY* p_array,
 271|  size_t p_array_sizeof, ThreeD_Poly* poly3, ThreeD_ViewL* view )
 272|{
 273|  int  i;
 274|  ThreeD_XYZ  p;
 275|
 276|  ERRORS_FUNC_START( TwoD_Poly_initByThreeD );
 277|
 278|  ASSERT( p_array_sizeof / sizeof( TwoD_XY ) >= (unsigned int)poly3->n );
 279|  p_array_sizeof;  /* avoid warning in release compile */
 280|
 281|  m->p_array = p_array;
 282|  m->n = poly3->n;
 283|  m->color = poly3->color;
 284|
 285|  for ( i = 0; i < m->n; i++ ) {
 286|    ThreeD_XYZ_get2D( &poly3->p_array[i], view, &p );
 287|    TwoD_XY_init( &m->p_array[i], p.x, p.y );
 288|  }
 289|
 290|  ERRORS_FUNC_END( TwoD_Poly_initByThreeD );
 291|}
 292|#endif /* USES_THREED */
 293|
 294|
 295| 
 296|#ifdef USES_THREED
 297|/*************************************************************************
 298|*  12. <<< [TwoD_Poly_initByThreeD2] 三次元ポリゴンから二次元ポリゴンを初期化する(2) >>> 
 299|*【機能】
 300|*・三次元ポリゴン poly3 を、「ThreeD_TwoD_initByPoly などの関数で f に
 301|*  定義された二次元座標」に変換して、二次元ポリゴン m を初期化します。
 302|*【引数】
 303|*  ・TwoD_XY*  p_array;    m の頂点を格納するワーク領域のアドレス
 304|*  ・ThreeD_TwoD*  f;      三次元空間内の二次元座標
 305|*  ・ThreeD_Poly*  poly3;  三次元ポリゴン
 306|**************************************************************************/
 307|void  TwoD_Poly_initByThreeD2( TwoD_Poly* m, TwoD_XY* p_array,
 308|  size_t p_array_sizeof, ThreeD_TwoD* f, ThreeD_Poly* poly3 )
 309|{
 310|  int  i;
 311|
 312|  ERRORS_FUNC_START( TwoD_Poly_initByThreeD2 );
 313|
 314|  ASSERT( p_array_sizeof / sizeof( TwoD_XY ) >= (unsigned int)poly3->n );
 315|  p_array_sizeof;  /* avoid warning in release compile */
 316|
 317|  /* 各種属性のコピー */
 318|  m->p_array = p_array;
 319|  m->n = poly3->n;
 320|  m->color = poly3->color;
 321|
 322|  /* 頂点座標の変換 */
 323|  for ( i = 0; i < m->n; i++ ) {
 324|    TwoD_XY_initBy3D( &m->p_array[i], f, &poly3->p_array[i] );
 325|  }
 326|
 327|  ERRORS_FUNC_END( TwoD_Poly_initByThreeD2 );
 328|}
 329|#endif /* USES_THREED */
 330|
 331|
 332| 
 333|/*************************************************************************
 334|*  13. <<< [TwoD_Poly_print] 属性をエラー表示する >>> 
 335|**************************************************************************/
 336|#ifndef  ERRORS_CUT_DEBUG_TOOL
 337|void  TwoD_Poly_print( TwoD_Poly* m )
 338|{
 339|  int  i;
 340|
 341|  ERRORS_FUNC_START( TwoD_Poly_print );
 342|
 343|  Errors_printf( "TwoD_Poly: n=%d, color=%d, ", m->n, m->color );
 344|  for ( i = 0; i < m->n; i++ )
 345|    Errors_printf( "(%lf,%lf), ", m->p_array[i].x, m->p_array[i].y );
 346|
 347|  ERRORS_FUNC_END( TwoD_Poly_print );
 348|}
 349|#endif
 350|
 351| 
 352|