1. 程式人生 > >判斷點是否在直線上

判斷點是否在直線上

這是一個純解析幾何的題目,不是有一個直線外一點到直線的距離公式嗎?是的,不過在GDI的領域,不需要這樣去考慮問題,不需要考慮直一方程,我們直接可以從座標對上著手。

struct CGeoXY
{
 double dx,dy;
};

/*引數說明

    pXY是一條直線的所有座標對陣列

    nPointCount是陣列中的點數

    dx,dy是要計算的點

    dOffset 是偏移量,即dx,dy與直線的距離差< dOffset 即可判斷為在直線上。

*/

bool isPtAtLine(CGeoXY* pXY, int nPointCount,double dx,double dy,double dOffset)
{
 double dx1,dy1,dx2,dy2;
 double dA1,dA2;

 for (int i = 0;i < nPointCount - 1;i++){
  dx1 = pXY[i].dx;
  dy1 = pXY[i].dy;

  dx2 = pXY[i + 1].dx;
  dy2 = pXY[i + 1].dy;

  if (isPtInRect(dx,dy,dx1,dy1,dx2,dy2)){
      dA1 = getDirection(dx1,dy1,dx,dy);
          dA2 = getDirection(dx1,dy1,dx2,dy2);

   if (abs(sin(dA1 - dA2) * getDistance(dx1,dy1,dx,dy)) < dOffset){
           return true;
   }
  }
  else{
   if (abs(dx1 - dx2) < dOffset){
    if (dy > min(dy1,dy2) && dy < max(dy1,dy2) && abs(dx - dx1) < dOffset){
     return true;
    }
   }
   if (abs(dy1 - dy2) < dOffset){
    if (dx > min(dx1,dx2) && dx < max(dx1,dx2) && abs(dy - dy1) < dOffset){
     return true;
    }
   }
  } 
 }
 return false;
}

裡面還用到了兩個函式:

/* 計算點是否在矩形範圍內*/

//left一定比right小,top一定比bottom小
bool isPtInRect(double dx,double dy, double dLeft,double dTop,double dRight,double dBottom)
{
 if (dLeft > dRight) { dLeft = dLeft + dRight; dRight = dLeft - dRight; dLeft = dLeft - dRight;}
 if (dTop > dBottom) { dTop = dTop + dBottom; dBottom = dTop - dBottom; dTop = dTop - dBottom;}

 if (dx < dLeft || dx > dRight || dy < dTop || dy > dBottom)
  return false;
 else
  return true;
}

/*計算兩點的斜率或角度,弧度*/

double getDirection(double dx1,double dy1,double dx2, double dy2)
{
 double dBufLen, dDirection;

 dBufLen = getDistance(dx1,dy1,dx2,dy2);

 if (abs(dx2 - dx1) < 10e-300) {
  if (abs(dy2 - dy1)< 10e-300){
  //等於沒有移動}
  }
  else {
   if ( dy1 - dy2 > 0) dDirection = PI/2;
   else dDirection = 3*PI/2;
  }
 }
 else {
  if (atan((dy1 - dy2)/(dx2 - dx1)) > 0){
   if (sin((dy1-dy2)/dBufLen)>0)
    dDirection = atan((dy1-dy2)/(dx2-dx1));
              else
    dDirection =atan((dy1-dy2)/(dx2 - dx1)) + PI;
  }
  else {
           if (sin((dy1-dy2)/dBufLen) > 0 )
    dDirection = atan((dy1-dy2)/(dx2 - dx1)) + PI;
   else
    dDirection = atan((dy1-dy2)/(dx2 - dx1));
           
   if (dDirection == 0 && dx1 > dx2) dDirection = PI;
  }
 }
 
 if (dDirection < 0) dDirection = 2 * PI + dDirection;
    return dDirection;
}