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|