//从圆弧一些信息得到圆弧上一个特殊的点(计算的是二维图形的情况)
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;
}
posted on 2010-09-08 10:12
老马驿站 阅读(670)
评论(0) 编辑 收藏 引用 所属分类:
c++