C:\home\SVGCats_src\src\Line.c
1|/************************************************************************** 2| 1. <<< ライン (Line) >>> 3|***************************************************************************/ 4| 5|#include "mixer_precomp.h" 6| 7|#ifdef USES_MXP_AUTOINC 8| #include <Line.ah> /* Auto include header, Look at mixer-... folder */ 9|#endif 10| 11| 12| 13|/*---------------------------------------------------------------------*/ 14|/* 2. <<<<◆(Line) ライン >>>> */ 15|/*---------------------------------------------------------------------*/ 16| 17| 18|/************************************************************************** 19| 2-1. <<< [Line_init] 初期化する >>> 20|【引数】 21| ・Line* m; ライン 22| ・int x1, y1; 頂点A 23| ・int x2, y2; 頂点B 24|***************************************************************************/ 25|void Line_init( Line* m, int x1, int y1, int x2, int y2 ) 26|{ 27| m->x1 = x1; m->y1 = y1; 28| m->x2 = x2; m->y2 = y2; 29|} 30| 31| 32| 33|/************************************************************************** 34| 2-2. <<< [Line_print] デバッグ表示する >>> 35|***************************************************************************/ 36|#ifndef ERRORS_CUT_DEBUG_TOOL 37|void Line_print( Line* m, const char* title ) 38|{ 39| Errors_printf( "%sLine[%p] = ( %d, %d ) - ( %d, %d )", title, 40| m->x1, m->y1, m->x2, m->y2 ); 41|} 42|#endif 43| 44| 45| 46|/*********************************************************************** 47| 2-3. <<< [Line_getDiff2FromPoint] ラインと点との距離の二乗を返す >>> 48|【引数】 49| ・Line* m; ライン 50| ・int x,y; 点の座標 51| ・int 返り値; ラインと点の距離の「二乗」 52|【補足】 53|・x,y が直線上であっても、2頂点の外にあるときは、頂点との距離になります。 54|・二乗を返しているのは、そのほうが計算が速く、二乗でも要求を満たすことが 55| できることがよくあるからです。 56|************************************************************************/ 57|int Line_getDiff2FromPoint( Line* m, int x, int y ) 58|{ 59| int a,b,c; 60| int r1, r2; 61| int X, Y; 62| int dd, dd2; 63| 64| /* 直線の式 aX+bY+c=0 の a,b,c を求める */ 65| a = m->y1 - m->y2; /* -(y2 - y1) */ 66| b = m->x2 - m->x1; 67| c = -( a * m->x1 ) - ( b * m->y1 ); 68| 69| if ( a != 0 || b != 0 ) { 70| 71| r1 = a*x + b*y + c; 72| r2 = a*a + b*b; 73| if ( r1 < 32768 && r1 >= -32768 ) { 74| 75| /* 直線(aX+bY+c=0) と点(x,y)の距離の公式 |ax+by+c| / sqrt(a*a + b*b) */ 76| /* から、距離の二乗 dd を求める */ 77| dd = (r1 * r1) / r2; 78| 79| /* ベクトル方程式:交点(X.Y) = (x,y) + t*(a,b) から、*/ 80| /* t= -(ax+by+c) / (a*a + b*b) */ 81| X = x + ( -r1 * a ) / r2; /* = x + ( -r1 / r2 ) * a */ 82| Y = y + ( -r1 * b ) / r2; /* = y + ( -r1 / r2 ) * b */ 83| } 84| 85| /* オーバーフロー対策 */ 86| else { 87| int s1, s2; 88| 89| s1 = r1 >> 5; s2 = r2 >> 10; 90| if ( s2 == 0 ) s2 = 1; /* r2 が小さすぎるとき */ 91| dd = (s1 * s1) / s2; 92| 93| /*s1 = r1 >> 5;*/ s2 = r2 >> 5; 94| X = x + ( -s1 * a ) / s2; 95| Y = y + ( -s1 * b ) / s2; 96| } 97| 98| /* 交点がラインの2頂点の中なら、dd を返す */ 99| if ( ( ( m->x1 <= X && X <= m->x2 ) || ( m->x2 <= X && X <= m->x1 ) ) && 100| ( ( m->y1 <= Y && Y <= m->y2 ) || ( m->y2 <= Y && Y <= m->y1 ) ) ) { 101| return dd; 102| } 103| } 104| 105| /* そうでないなら、2頂点の近いほうの距離を返す */ 106| r1 = ( m->x1 - x ); 107| r2 = ( m->y1 - y ); 108| dd = r1*r1 + r2*r2; 109| 110| r1 = ( m->x2 - x ); 111| r2 = ( m->y2 - y ); 112| dd2 = r1*r1 + r2*r2; 113| 114| if ( dd < dd2 ) return dd; 115| else return dd2; 116|} 117| 118| 119|/*********************************************************************** 120| 2-4. <<< [Line_isCrossToRect] 矩形とラインが位置的に共通している部分があるかどうかを返す >>> 121|************************************************************************/ 122|#ifdef USES_RECT 123|bool Line_isCrossToRect( Line* m, Rect* r ) 124|{ 125| int f1, f2, f, n, a, b, c, x, y; 126| 127| /* 矩形と2頂点の位置関係をアバウトに解析する 128| 1)1010:2 2)0010:1 3)0110:2 o 1-3:1100:4 o 1-7:0011:4 x 4-2:1010:2 129| 4)1000:1 5)0000:0 6)0100:1 x 1-6:1110:3 x 1-8:1011:3 x 4-3:1110:3 130| 7)1001:2 8)0001:1 9)0101:2 o 1-4:0010:3 x 1-9:1111:4 x 4-6:1100:2 131| */ 132| f1 = 0; f2 = 0; n = 0; 133| 134| if ( m->x1 < r->x ) { f1 ^= 0x8; n++; } 135| if ( m->x1 > r->x + r->w ) { f1 ^= 0x4; n++; } 136| if ( m->y1 < r->y ) { f1 ^= 0x2; n++; } 137| if ( m->y1 > r->y + r->h ) { f1 ^= 0x1; n++; } 138| if ( m->x2 < r->x ) { f2 ^= 0x8; n++; } 139| if ( m->x2 > r->x + r->w ) { f2 ^= 0x4; n++; } 140| if ( m->y2 < r->y ) { f2 ^= 0x2; n++; } 141| if ( m->y2 > r->y + r->h ) { f2 ^= 0x1; n++; } 142| 143| f = f1 ^ f2; 144| 145| if ( n < 2 ) 146| return true; 147| else if ( n == 2 ) { 148| if ( f == 0 ) return false; 149| else if ( f1 == 0 || f2 == 0 ) return true; 150| else if ( (f & 0xC) == 0x0 || (f & 0x3) == 0x0 ) return true; 151| } 152| else { 153| if ( (f & 0xC) == 0x0 || (f & 0x3) == 0x0 ) return false; 154| } 155| 156| 157| /* 直線の式 aX+bY+c=0 から厳密に調べる */ 158| a = m->y1 - m->y2; /* -(y2 - y1) */ 159| b = m->x2 - m->x1; 160| c = -( a * m->x1 ) - ( b * m->y1 ); 161| 162| if ( f & 0x8 ) { 163| y = ( -a * r->x - c ) / b; 164| if ( r->y <= y && y <= r->y + r->h ) return true; 165| } 166| else { 167| y = ( -a * (r->x + r->w) - c ) / b; 168| if ( r->y <= y && y <= r->y + r->h ) return true; 169| } 170| 171| if ( f & 0x2 ) { 172| x = ( -b * r->y - c ) / a; 173| if ( r->x <= x && x <= r->x + r->w ) return true; 174| } 175| else { 176| x = ( -b * (r->y + r->h) - c ) / a; 177| if ( r->x <= x && x <= r->x + r->w ) return true; 178| } 179| 180| return false; 181|} 182|#endif 183| 184|/*********************************************************************** 185| 2-5. <<< [Line_getHitHandleNum] CadPrim::GetHitHandleNum の実装部 >>> 186|【補足】 187|・ハンドル番号は、頂点Aが1、頂点Bが2です。 188|・ハンドルの数は、Line_nHandle です。 189|************************************************************************/ 190|int Line_getHitHandleNum( Line* m, int x, int y, int zoom, int width, 191| int* dx, int* dy, int* diff, int* arrow ) 192|{ 193| int dx1, dy1, dx2, dy2; 194| int diff1 = 7; 195| int diff2 = 3 + width; 196| 197| diff1 = diff1 * 100 / zoom; if ( diff1 < 1 ) diff1 = 1; 198|// diff2 = diff2 * 100 / zoom; if ( diff2 < 1 ) diff2 = 1; 199| 200| dx1 = m->x1 - x; 201| dy1 = m->y1 - y; 202| dx2 = m->x2 - x; 203| dy2 = m->y2 - y; 204| 205| *dx = 0; *dy = 0; 206| 207| if ( dx1 >= -diff1 && dx1 <= diff1 && dy1 >= -diff1 && dy1 <= diff1 ) { 208| *arrow = CadPrim_CrossArrow; 209| *dx = m->x1 - x; 210| *dy = m->y1 - y; 211| return 1; 212| } 213| else if ( dx2 >= -diff1 && dx2 <= diff1 && dy2 >= -diff1 && dy2 <= diff1 ) { 214| *arrow = CadPrim_CrossArrow; 215| *dx = m->x2 - x; 216| *dy = m->y2 - y; 217| return 2; 218| } 219| 220| else if ( Line_getDiff2FromPoint( m, x, y ) < diff2*diff2) { 221| *dx = m->x1 - x; 222| *dy = m->y1 - y; 223| *arrow = CadPrim_MovableArrow; 224| return -1; 225| } 226| else { 227| *arrow = CadPrim_NormalArrow; 228| return 0; 229| } 230|} 231| 232| 233|/*********************************************************************** 234| 2-6. <<< [Line_moveByHandle] CadPrim::MoveByHandle の実装部 >>> 235|************************************************************************/ 236|void Line_moveByHandle( Line* m, int iHandle, int x, int y, bool bShift ) 237|{ 238| int dx, dy; 239| enum { diff = 6 }; 240| 241| switch ( iHandle ) { 242| case 1: 243| if ( bShift ) 244| { m->x1 = x; m->y1 = y; } 245| else { 246| dx = x - m->x2; 247| dy = y - m->y2; 248| if ( dx >= -diff && dx <= diff ) { 249| if ( dy >= -diff && dy <= diff ) 250| { m->x1 = x; m->y1 = y; } 251| else 252| { m->x1 = m->x2; m->y1 = y; } 253| } 254| else if ( dy >= -diff && dy <= diff ) 255| { m->x1 = x; m->y1 = m->y2; } 256| else 257| { m->x1 = x; m->y1 = y; } 258| } 259| break; 260| 261| case 2: 262| if ( bShift ) 263| { m->x2 = x; m->y2 = y; } 264| else { 265| dx = x - m->x1; 266| dy = y - m->y1; 267| if ( dx >= -diff && dx <= diff ) { 268| if ( dy >= -diff && dy <= diff ) 269| { m->x2 = x; m->y2 = y; } 270| else 271| { m->x2 = m->x1; m->y2 = y; } 272| } 273| else if ( dy >= -diff && dy <= diff ) 274| { m->x2 = x; m->y2 = m->y1; } 275| else 276| { m->x2 = x; m->y2 = y; } 277| } 278| break; 279| 280| case -1: { 281| dx = x - m->x1; 282| dy = y - m->y1; 283| 284| m->x1 = x; m->y1 = y; 285| m->x2 += dx; m->y2 += dy; 286| break; 287| } 288| } 289|} 290| 291| 292|/*********************************************************************** 293| 2-7. <<< [Line_getCenterOfHandle] ハンドルの中心座標を取得する >>> 294|【引数】 295| ・Line* m; ライン 296| ・int iHandle; ハンドル番号(1〜Line_nHandle) 297| ・int* x,y; 座標を格納する領域のアドレス 298|【補足】 299|・ハンドルについては、Line_getHitHandleNum を参照。 300|************************************************************************/ 301|void Line_getCenterOfHandle( Line* m, int iHandle, int* x, int* y ) 302|{ 303| switch ( iHandle ) { 304| case 1: 305| *x = m->x1; *y = m->y1; 306| break; 307| 308| case 2: 309| *x = m->x2; *y = m->y2; 310| break; 311| } 312|} 313| 314| 315|