假如已经知道P1,P2,凸度bulge(H/L),需要计算P1到P2凸度圆弧圆心 和 BOX。
(1)根据 P1,P2的距离,得出 L的值,根据 bulge 得出 H = L*bulge;
(2)计算圆心:根据勾股定理,L*L+H2*H2=E*E; H*H+L*L+E*E = (H+H2)*(H+H2);
联立两个方程,可以得出 L*L = H*H2; 从而得出 H2的值,由 H和 H2 可以获得半径,H-H2所在直线和圆的两个交点,这两个交点的中点就是圆心。
(3)计算BOX:P1,P2肯定要加入BOX。象限点可以通过判断几个象限点是否在圆弧上,来判断是否把象限点加入 BOX。判断象限点是否在圆弧上,可以通过判断象限点是否在P1-P2组成的直线的某一侧(向量叉乘)来获得象限点是否在圆弧上
代码如下
void GetCurSegBox(XYZ i_Pt1, XYZ i_Pt2, double i_dBulge, CBox& o_Box)const
{
XYZ MinPos, MaxPos;//最大最小顶点
MinPos.x = min(i_Pt1.x, i_Pt2.x);
MinPos.y = min(i_Pt1.y, i_Pt2.y);
MinPos.z = min(i_Pt1.z, i_Pt2.z);
MaxPos.x = max(i_Pt1.x, i_Pt2.x);
MaxPos.y = max(i_Pt1.y, i_Pt2.y);
MaxPos.z = max(i_Pt1.z, i_Pt2.z);
XYZ arcpt1, arcpt2;
XYZ mpt((i_Pt1.x + i_Pt2.x) / 2.0, (i_Pt1.y + i_Pt2.y) / 2.0, (i_Pt1.z + i_Pt2.z) / 2.0);
double dL = 0.0, dH;
i_Pt1.GetDistToPt(mpt, dL);
dH = fabs(i_dBulge) * dL;
CVector Dir(i_Pt1, i_Pt2);
Dir.Unit();
double dH2 = dL * dL / dH;
double dR = (dH + dH2) * 0.5;
double dPara = 1.0;
if (i_dBulge < 0.0)
dPara = -1.0;
CVector Dir1(Dir.y * dPara, -(Dir.x * dPara), 0.0);
CVector Dir2(-(Dir.y * dPara), Dir.x * dPara, 0.0);
CxGeLnSeg ln1(mpt, Dir1, dH);
CxGeLnSeg ln2(mpt, Dir2, dH2);
ln1.GetEndPt(arcpt1);
ln2.GetEndPt(arcpt2);
XYZ arcCent((arcpt1.x + arcpt2.x) / 2.0, (arcpt1.y + arcpt2.y) / 2.0, (arcpt1.z + arcpt2.z) / 2.0);
//判断四个象限点是否在圆弧上
XYZ quadPts[4] = { XYZ(arcCent.x + dR, arcCent.y, 0.0),
XYZ(arcCent.x, arcCent.y + dR, 0.0),
XYZ(arcCent.x - dR, arcCent.y, 0.0),
XYZ(arcCent.x, arcCent.y - dR, 0.0) };
for (int i = 0; i < 4; i++)
{
XYZ& quadPt = quadPts[i];
CVector DirQuad(quadPt.x - i_Pt1.x, quadPt.y - i_Pt1.y, 0.0);
CVector crossVec;
DirQuad.GetCrossProd(Dir, crossVec);
if (crossVec.z * dPara > 0.0)
{
MinPos.x = min(MinPos.x, quadPt.x);
MinPos.y = min(MinPos.y, quadPt.y);
MinPos.z = min(MinPos.z, quadPt.z);
MaxPos.x = max(MaxPos.x, quadPt.x);
MaxPos.y = max(MaxPos.y, quadPt.y);
MaxPos.z = max(MaxPos.z, quadPt.z);
}
}
o_Box.SetMinPos(MinPos);
o_Box.SetMaxPos(MaxPos);
}