Line.c

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|