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; }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值