已知圆弧的一些信息,求得圆弧上中间点的坐标的方法(C++语言描述)

已知圆弧的一些信息,求得圆弧上中间点的坐标的方法(C++语言描述)
// 从圆弧一些信息得到圆弧上一个特殊的点(计算的是二维图形的情况)
Point3d DBOPERATION::GetArcTangencyPoint(Point3d pStartPoint, Point3d pEndPoint,
                                         Point3d pCenterPoint, 
double  dRadius,
                                         
double  dStartAngle,  double  dSweepAngle)
{
    Point3d pResultPoint;
    pResultPoint.X 
=   0 ;
    pResultPoint.Y 
=   0 ;
    pResultPoint.Z 
=   0 ;

    
// 因为会得到两个点,哪个点在弧上需要再进行判断
     double  dRx1  =   0 ;
    
double  dRx2  =   0 ;
    
double  dRy1  =   0 ;
    
double  dRy2  =   0 ;

    
const   double  PI  =   3.1415926535897932 ;

    Point3d pMiddlePoint;
    pMiddlePoint.X 
=  (pStartPoint.X  +  pEndPoint.X)  /   2 ;
    pMiddlePoint.Y 
=  (pStartPoint.Y  +  pEndPoint.Y)  /   2 ;
    pMiddlePoint.Z 
=   0.0 ;

    
// 扫角的角度值
     double  dArcSweepAngle  =   180   *  dSweepAngle  /  PI;
    
// 中点到圆心的距离
     double  ddy  =   0 ;
    
double  ddx  =   0 ;
    
if  (pMiddlePoint.X  -  pCenterPoint.X  >=   0.1e-6 )
    {
        ddx 
=  pMiddlePoint.X  -  pCenterPoint.X;
    }
    
if  (pMiddlePoint.Y  -  pCenterPoint.Y  >=   0.1e-6 )
    {
        ddx 
=  pMiddlePoint.Y  -  pCenterPoint.Y;
    }
    
double  dDistance  =  sqrt(ddx  *  ddx  +  ddy  *  ddy);

    
if  ((fabs(pMiddlePoint.Y  -  pCenterPoint.Y)  <   0.1e-6
        
&&  fabs(pMiddlePoint.X  -  pCenterPoint.X)  <   0.1e-6 )
        
&&  (fabs(pStartPoint.X  -  pEndPoint.X)  <   0.1e-6
        
||  fabs(pStartPoint.Y  -  pEndPoint.Y)  < 0.1e-6  ))
    {
        
// 半圆且斜率=0或者斜率为无穷大的情况
         if  (fabs(pStartPoint.X  -  pEndPoint.X)  <   0.1e-6 )
        {
            
// 结果的两个X的值
            dRx1  =  pMiddlePoint.X  +  (dRadius  -  dDistance);
            dRx2 
=  pMiddlePoint.X  -  (dRadius  +  dDistance);
            
// 对应的两个Y的值
            dRy1  =  pMiddlePoint.Y;
            dRy2 
=  pMiddlePoint.Y;
        }
        
if  (fabs(pStartPoint.Y  -  pEndPoint.Y)  < 0.1e-6 )
        {
            
// 结果的两个X的值
            dRx1  =  pMiddlePoint.X;
            dRx2 
=  pMiddlePoint.X;
            
// 对应的两个Y的值
            dRy1  =  pMiddlePoint.Y  +  (dRadius  -  dDistance);
            dRy2 
=  pMiddlePoint.Y  -  (dRadius  +  dDistance);
        }
    }
    
else   if  (fabs(pMiddlePoint.Y  -  pCenterPoint.Y)  <   0.1e-6
        
&&  fabs(pMiddlePoint.X  -  pCenterPoint.X)  >=   0.1e-6 )
    {
        
// 圆心与端点中心点在水平线上的情况,斜率=0
        
// 结果的两个X的值
        dRx1  =  pMiddlePoint.X  +  (dRadius  -  dDistance);
        dRx2 
=  pMiddlePoint.X  -  (dRadius  +  dDistance);
        
// 对应的两个Y的值
        dRy1  =  pMiddlePoint.Y;
        dRy2 
=  pMiddlePoint.Y;
    }
    
else   if  (fabs(pMiddlePoint.X  -  pCenterPoint.X)  <   0.1e-6
        
&&  fabs(pMiddlePoint.Y  -  pCenterPoint.Y)  >=   0.1e-6 )
    {
        
// 圆心与端点中心点在垂直线上的情况,斜率=无穷大
        
// 结果的两个X的值
        dRx1  =  pMiddlePoint.X;
        dRx2 
=  pMiddlePoint.X;
        
// 对应的两个Y的值
        dRy1  =  pMiddlePoint.Y  +  (dRadius  -  dDistance);
        dRy2 
=  pMiddlePoint.Y  -  (dRadius  +  dDistance);
    }
    
else
    {
        
// 圆弧两个端点成线的斜率,已经排除了等于0或者无穷大的可能性
         double  dTheKSAE  =  (pEndPoint.Y  -  pStartPoint.Y)  /  (pEndPoint.X  -  pStartPoint.X);
        
// 与端点组成的线垂直的线的斜率(0度,180度,360度弧的dk需要特殊处理)
         double  dK  =  ( 1   /  dTheKSAE)  *  ( - 1 );

        
if  (fabs(fabs(dArcSweepAngle)  -   360 <   0.1e-6 )
        {
            dK 
=  (pMiddlePoint.Y  -  pCenterPoint.Y)  /  (pMiddlePoint.X  -  pCenterPoint.X);
        }
        
if  (fabs(fabs(dArcSweepAngle)  -   180 <   0.1e-6 )
        {
            dK 
=  (pStartPoint.Y  -  pCenterPoint.Y)  /  (pStartPoint.X  -  pCenterPoint.X);
            dK 
=  ( 1   /  dK)  *  ( - 1 );
        }
        
if  (fabs(fabs(dArcSweepAngle)  -   0 <   0.1e-6 )
        {
            dK 
=  (pMiddlePoint.Y  -  pCenterPoint.Y)  /  (pMiddlePoint.X  -  pCenterPoint.X);
        }
        
/////////////////////////////////////////////////////////
         // 这是经过两端点中点并与两端点组成的直线垂直的直线的方程
        
// k为斜率,M(x),M(y)分别为中心点坐标值
        
// y=k * x - k * M(x) + M(y)
         /////////////////////////////////////////////////////////

        
// 求出- k * M(x) + M(y)部分的值
         double  dDif  =  ( - 1 *  dK  *  pMiddlePoint.X  +  pMiddlePoint.Y;

        
/////////////////////////////////////////////////////////
         //  [x - C(x)]^2 + [y - C(y)]^2 = r^2
        
//  代入上面的y,其中- k * M(x) + M(y)以dDif代替
        
//  [x - C(x)]^2 + [kx + dDif - C(y)]^2 = r^2
        
//  下面以dBetween代替+ dDif - C(y)
         /////////////////////////////////////////////////////////
         double  dBetween  =  dDif  -  pCenterPoint.Y;

        
/////////////////////////////////////////////////////////
         //  x^2 + 2*C(x)*x + [C(x)]^2
        
//  +
        
//  (kx)^2 + 2*k*dBetween*x + (dBetween)^2
        
//  = r^2
         /////////////////////////////////////////////////////////

        
// 再求中间值
         double  dNx  =  ( 2   *  dK  *  dBetween  -   2   *  pCenterPoint.X)  /  ( 1   +  dK  *  dK);
        
double  dLa  =  (dRadius  *  dRadius  -  pCenterPoint.X  *  pCenterPoint.X
            
-  dBetween  *  dBetween)  /  ( 1   +  dK  *  dK);
        
double  dAd  =  dLa  +  dNx  *  dNx  /   4 ;

        
// 结果的两个X的值
        dRx1  =  sqrt(dAd)  -  dNx  /   2 ;
        dRx2 
=  ( - 1 *  sqrt(dAd)  -  dNx  /   2 ;
        
// 对应的两个Y的值
        dRy1  =  dK  *  dRx1  -  dK  *  pMiddlePoint.X  +  pMiddlePoint.Y;
        dRy2 
=  dK  *  dRx2  -  dK  *  pMiddlePoint.X  +  pMiddlePoint.Y;
    }

    
// 对得到的两个点进行判断,找到在弧上的那个
    pResultPoint.X  =  dRx1;
    pResultPoint.Y 
=  dRy1;
    
if  (fabs(fabs(dArcSweepAngle)  -   180.0 <   0.1e-4 )
    {
        
// 半圆情况处理
         double  p1x,p1y,p2x,p2y,qx,qy,dx1,dy1,dx2,dy2,det;
        p2x 
=  pStartPoint.X;
        p2y 
=  pStartPoint.Y;
        p1x 
=  pCenterPoint.X;
        p1y 
=  pCenterPoint.Y;
        qx 
=  dRx2;
        qy 
=  dRy2;

        dx1 
=  p2x  -  p1x;
        dy1 
=  p2y  -  p1y;
        dx2 
=  qx -  p2x;
        dy2 
=  qy  -  p2y;
        det 
=  dx1 * dy2  -  dx2 * dy1;
        BOOL bBlockWise 
=  TRUE;
        
if  (det  >   0.0 )
        {
            
// 逆时针方向
            bBlockWise  =  FALSE;
        }
        
if  ((( ! bBlockWise)  &&  (dArcSweepAngle  >   0.0 ))
            
||  ((bBlockWise)  &&  (dArcSweepAngle  <   0.0 )))
        {
            pResultPoint.X 
=  dRx2;
            pResultPoint.Y 
=  dRy2;
        }
    }
    
else
    {
        
// 非半圆的情况
         double  dd1  =  sqrt(pow(dRx1  -  pMiddlePoint.X,  2 )
            
+  pow(dRy1  -  pMiddlePoint.Y,  2 ));
        
double  dd2  =  sqrt(pow(dRx2  -  pMiddlePoint.X,  2 )
            
+  pow(dRy2  -  pMiddlePoint.Y,  2 ));
        
if  (((dd1  <  dd2)  &&  (fabs(dArcSweepAngle)  >   180.0 ))
            
||  ((dd1  >  dd2)  &&  (fabs(dArcSweepAngle)  <   180.0 )))
        {
            pResultPoint.X 
=  dRx2;
            pResultPoint.Y 
=  dRy2;
        }
    }

    
return  pResultPoint;
}

你可能感兴趣的:(已知圆弧的一些信息,求得圆弧上中间点的坐标的方法(C++语言描述))