gogogo168 发表于 2005-9-16 15:31:00

[VBA]AutoCAD VBA开发精彩实例教程的错误

最近看同事的《AutoCAD VBA开发精彩实例教程》,是你们网站张帆等编著的书。发现在53页,三点法画弧中所示例的程序代码是错误的!!!当用Set objArc=AddArcCSEP(ptCen,ptSt,ptEn)画弧时,所画的圆弧永远都是逆时针方向的。很可能不通过第二点!!请高手示例正确的代码以解我的疑惑!!!

MJTD_7777 发表于 2005-9-16 15:36:00

<P>你在那里买的这书,有电子版吗?能把书中附带的东西发上来吗?</P>

gogogo168 发表于 2005-9-17 10:01:00

估计斑竹不会同意的

mccad 发表于 2005-9-18 07:51:00

圆弧只有一个方向,没有正反之分。<BR>需要你给出三个点的数据来证明这个程序有问题。注意:三个点的中间那个点不代表就是圆弧的中点,所以你用圆弧的中点来与中间那个点比较肯定是不同的。

gogogo168 发表于 2005-9-18 16:17:00

<P>其实只要是顺时针方向画的三个点,画出来的圆弧都有问题!!!我编一个小函数来验证:</P>
<P>Sub ttest()<BR>Dim aPoint(2) As Double<BR>Dim bPoint(2) As Double<BR>Dim cPoint(2) As Double<BR>aPoint(0) = 1340<BR>aPoint(1) = 610<BR>bPoint(0) = 1434<BR>bPoint(1) = 505<BR>cPoint(0) = 1369<BR>cPoint(1) = 335<BR>Dim t As Variant<BR>'''创建三点所画的弧<BR>Set t = f_AddArc3Pt(aPoint, bPoint, cPoint)<BR>Dim lwPLine As AcadLWPolyline<BR>Dim pp(0 To 5) As Double<BR>pp(0) = 1340<BR>pp(1) = 610<BR>pp(2) = 1434<BR>pp(3) = 505<BR>pp(4) = 1369<BR>pp(5) = 335<BR>'''创建三点所画的直线<BR>Set lwPLine = ThisDrawing.ModelSpace.AddLightWeightPolyline(pp)<BR>End Sub<BR>比较弧和线就会发现问题!不通过的二点</P>

gogogo168 发表于 2005-9-18 16:19:00

<P>同时附上你们的程序代码:</P>
<P>Private Function GetCenOf3Pt(pt1 As Variant, pt2 As Variant, pt3 As Variant, ByRef radius As Double) As Variant<BR>''''根据三点计算出圆心和半径<BR>Dim xysm, xyse, xy As Double<BR>Dim ptCen(2) As Double<BR>xy = pt1(0) ^ 2 + pt1(1) ^ 2<BR>xyse = xy - pt3(0) ^ 2 - pt3(1) ^ 2<BR>xysm = xy - pt2(0) ^ 2 - pt2(1) ^ 2<BR>xy = (pt1(0) - pt2(0)) * (pt1(1) - pt3(1)) - (pt1(0) - pt3(0)) * (pt1(1) - pt2(1))<BR>'''判断参数有效性<BR>If Abs(xy) &lt; 0.000001 Then<BR>&nbsp;&nbsp; MsgBox "所输入的参数无法创建圆形!"<BR>&nbsp;&nbsp; Exit Function<BR>End If<BR>'获得圆心和半径<BR>ptCen(0) = (xysm * (pt1(1) - pt3(1)) - xyse * (pt1(1) - pt2(1))) / (2 * xy)<BR>ptCen(1) = (xyse * (pt1(0) - pt2(0)) - xysm * (pt1(0) - pt3(0))) / (2 * xy)<BR>ptCen(2) = 0<BR>radius = Sqr((pt1(0) - ptCen(0)) * (pt1(0) - ptCen(0)) + (pt1(1) - ptCen(1)) * (pt1(1) - ptCen(1)))<BR>If radius &lt; 0.000001 Then<BR>&nbsp;&nbsp; MsgBox "半径过小!"<BR>&nbsp;&nbsp; Exit Function<BR>End If<BR>''函数返回圆心的位置,而半径则在参数中通过引用方式返回<BR>GetCenOf3Pt = ptCen<BR>End Function<BR>Public Function AddArc3Pt(ByVal ptSt As Variant, ByVal ptSc As Variant, ByVal ptEn As Variant) As AcadArc<BR>''''三点法创建圆弧<BR>Dim objArc As AcadArc<BR>Dim ptCen As Variant<BR>Dim radius As Double<BR>ptCen = GetCenOf3Pt(ptSt, ptSc, ptEn, radius)<BR>Set objArc = AddArcCSEP(ptCen, ptSt, ptEn)</P>
<P>objArc.Update<BR>Set AddArc3Pt = objArc<BR>End Function<BR>Private Function AddArcCSEP(ByVal ptCen As Variant, ByVal ptSt As Variant, ByVal ptEn As Variant) As AcadArc<BR>Dim objArc As AcadArc<BR>Dim radius As Double<BR>Dim stAng, enAng As Double<BR>''计算半径<BR>radius = GetDistance(ptCen, ptSt)<BR>''计算起点角度和终点角度<BR>stAng = ThisDrawing.Utility.AngleFromXAxis(ptCen, ptSt)<BR>enAng = ThisDrawing.Utility.AngleFromXAxis(ptCen, ptEn)</P>
<P>Set objArc = ThisDrawing.ModelSpace.AddArc(ptCen, radius, stAng, enAng)<BR>objArc.Update<BR>Set AddArcCSEP = objArc<BR>End Function</P>

mccad 发表于 2005-9-18 17:59:00

Public Function AddArc3Pt(ByVal ptSt As Variant, ByVal ptSc As Variant, ByVal ptEn As Variant) As AcadArc
''''三点法创建圆弧
Dim objArc As AcadArc
Dim ptCen As Variant
Dim radius As Double
ptCen = GetCenOf3Pt(ptSt, ptSc, ptEn, radius)
If isClockWise(ptSt, ptSc, ptEn) Then
    Set objArc = AddArcCSEP(ptCen, ptSt, ptEn)
Else
    Set objArc = AddArcCSEP(ptCen, ptEn, ptSt)
End IfobjArc.Update
Set AddArc3Pt = objArc
End Function
'判断三点的方向
Function isClockWise(ptSt, ptSc, ptEn) As Boolean
    If (ThisDrawing.Utility.AngleFromXAxis(ptSt, ptSc) - ThisDrawing.Utility.AngleFromXAxis(ptSc, ptEn) < 0 _
    And ThisDrawing.Utility.AngleFromXAxis(ptSt, ptSc) - ThisDrawing.Utility.AngleFromXAxis(ptSc, ptEn) > -3.14159265) _
    Then isClockWise = True
End Function

gogogo168 发表于 2005-9-19 14:20:00

<P>帅哥,你的算法还是有问题!!比如:</P>
<P>Sub ttest()<BR>Dim aPoint(2) As Double<BR>Dim bPoint(2) As Double<BR>Dim cPoint(2) As Double<BR>aPoint(0) = 19358<BR>aPoint(1) = -3402<BR>bPoint(0) = 20779<BR>bPoint(1) = -4141<BR>cPoint(0) = 22649<BR>cPoint(1) = -1360<BR>Dim t As Variant<BR>'''创建三点所画的弧<BR>Set t = f_AddArc3Pt(aPoint, bPoint, cPoint)<BR>Dim lwPLine As AcadLWPolyline<BR>Dim pp(0 To 5) As Double<BR>pp(0) = 19358<BR>pp(1) = -3402<BR>pp(2) = 20779<BR>pp(3) = -4141<BR>pp(4) = 22649<BR>pp(5) = -1360<BR>'''创建三点所画的直线<BR>Set lwPLine = ThisDrawing.ModelSpace.AddLightWeightPolyline(pp)<BR>End Sub<BR></P>

gogogo168 发表于 2005-9-19 22:20:00

'判断三点的方向(自己改了一下,供大家测试)<BR>Function isClockWise(ptSt, ptSc, ptEn) As Boolean<BR>'''顺时针为false,逆时针为true<BR>Dim y As Double<BR>If ptSc(0) &gt; ptSt(0) Then&nbsp;&nbsp; '在右半边<BR>&nbsp;&nbsp; y = ((ptSc(1) - ptSt(1)) * ptEn(0) + ptSt(1) * ptSc(0) - ptSt(0) * ptSc(1)) / (ptSc(0) - ptSt(0))<BR>&nbsp;&nbsp; If y &gt; ptEn(1) Then '如果在线下面<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isClockWise =&nbsp;false<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isClockWise =&nbsp;true<BR>&nbsp;&nbsp; End If<BR>&nbsp;&nbsp; Exit Function<BR>End If<BR>If ptSc(0) &lt; ptSt(0) Then&nbsp;&nbsp;&nbsp; '在左半边<BR>&nbsp;&nbsp; y = ((ptSc(1) - ptSt(1)) * ptEn(0) + ptSt(1) * ptSc(0) - ptSt(0) * ptSc(1)) / (ptSc(0) - ptSt(0))<BR>&nbsp;&nbsp; If y &gt; ptEn(1) Then '如果在线下面<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isClockWise =true<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isClockWise =&nbsp;false<BR>&nbsp;&nbsp; End If<BR>&nbsp;&nbsp; Exit Function<BR>End If<BR>If (ptSc(0) = ptSt(0)) And (ptSc(1) &gt; ptSt(1)) Then&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '90度<BR>&nbsp;&nbsp; If ptEn(0) &gt; ptSc(0) Then&nbsp;&nbsp; '右顺<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isClockWise =&nbsp;false<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isClockWise =&nbsp;true<BR>&nbsp;&nbsp; End If<BR>&nbsp;&nbsp; Exit Function<BR>End If<BR>If (ptSc(0) = ptSt(0)) And (ptSc(1) &lt; ptSt(1)) Then&nbsp;&nbsp;&nbsp; '270度<BR>&nbsp;&nbsp; If ptEn(0) &gt; ptSc(0) Then&nbsp;&nbsp; '左顺<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isClockWise =true<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isClockWise =&nbsp;false<BR>&nbsp;&nbsp; End If<BR>&nbsp;&nbsp; Exit Function<BR>End If<BR>End Function<BR>

雪山飞狐_lzh 发表于 2005-9-19 23:27:00

本帖最后由 作者 于 2006-3-23 13:18:30 编辑 <br /><br /> <P>Public Function AddArc3Pt(ByVal ptSt As Variant, ByVal ptSc As Variant, ByVal ptEn As Variant) As AcadArc<BR>''''三点法创建圆弧<BR>Dim objArc As AcadArc<BR>Dim ptCen As Variant<BR>Dim radius As Double<BR>ptCen = GetCenOf3Pt(ptSt, ptSc, ptEn, radius)<BR>If isClockWise(ptCen, ptSt, ptSc, ptEn) Then<BR>&nbsp;&nbsp;&nbsp; Set objArc = AddArcCSEP(ptCen, ptSt, ptEn)<BR>Else<BR>&nbsp;&nbsp;&nbsp; Set objArc = AddArcCSEP(ptCen, ptEn, ptSt)<BR>End If<BR>objArc.Update<BR>Set AddArc3Pt = objArc<BR>End Function<BR></P>
<P>Private Function AddArcCSEP(ByVal ptCen As Variant, ByVal ptSt As Variant, ByVal ptEn As Variant) As AcadArc<BR>Dim objArc As AcadArc<BR>Dim radius As Double<BR>Dim stAng, enAng As Double<BR>''计算半径<BR>radius = GetDistance(ptCen, ptSt)<BR>''计算起点角度和终点角度<BR>stAng = ThisDrawing.Utility.AngleFromXAxis(ptCen, ptSt)<BR>enAng = ThisDrawing.Utility.AngleFromXAxis(ptCen, ptEn)</P>
<P>Set objArc = ThisDrawing.ModelSpace.AddArc(ptCen, radius, stAng, enAng)<BR>objArc.Update<BR>Set AddArcCSEP = objArc<BR>End Function</P>

<P>'判断三点的方向<BR>Function isClockWise(ptCen, ptSt, ptSc, ptEn) As Boolean<BR>&nbsp;&nbsp;&nbsp; a1 = ThisDrawing.Utility.AngleFromXAxis(ptCen, ptSt)<BR>&nbsp;&nbsp;&nbsp; a2 = ThisDrawing.Utility.AngleFromXAxis(ptCen, ptSc)<BR>&nbsp;&nbsp;&nbsp; a3 = ThisDrawing.Utility.AngleFromXAxis(ptCen, ptEn)<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;isClockWise = (a1 &lt; a2) Xor (a2 &lt; a3) Xor (a1 &lt; a3)<BR>&nbsp;&nbsp;&nbsp; <BR>End Function</P>
<P>'说明,逆时针的三种情况如下,其余为顺时针</P>
页: [1] 2
查看完整版本: [VBA]AutoCAD VBA开发精彩实例教程的错误