[分享]给一个点和一段多段线,求出这个点到多段线的最短距离吗?
本帖最后由 作者 于 2005-3-22 16:53:12 编辑 <br /><br /> <FONT id=text1 style="FONT-SIZE: 10pt" face="宋体,verdana, arial, helvetica">[求助]有谁用VBA写过给一个点和一段多段线,求出这个点到多段线的最短距离吗?好写但是现在我还有其他的问题很忙,不晓得有没有哪位好心人写过(我觉得应该有人碰到过这个问题)</FONT> <BR> 自己写了,不晓得对不对!请明总看看,还有就是我的变量名字可能不是很规范!Option Explicit
Sub disPtLwline()
Dim disPtline As Double<BR> Dim mindisPtline As Double<BR> Dim p1 As Variant<BR> Dim p2(0 To 2) As Double<BR> p1 = ThisDrawing.Utility.GetPoint(, " 请输入点:")<BR> p2(0) = p1(0): p2(1) = p1(1): p2(2) = 0<BR> Dim objPline As AcadLWPolyline<BR> Dim mlwlineqidian1 As AcadEntity<BR> Dim mlwlineqidian2 As Variant<BR> ThisDrawing.Utility.GetEntity mlwlineqidian1, mlwlineqidian2, "请选择多段线"<BR> If TypeOf mlwlineqidian1 Is AcadLWPolyline Then<BR> Set objPline = mlwlineqidian1<BR> End If<BR> <BR> <BR> <BR>Dim intVCnt As Integer<BR>Dim varCords As Variant<BR>Dim varVert As Variant<BR>Dim varCord As Variant<BR>Dim varNext As Variant<BR>Dim intCrdCnt As Integer<BR>Dim dblXSl As Double<BR>Dim dblYSl As Double<BR>Dim dblZSl As Double<BR>Dim dblTemp As Double<BR>Dim dblTemp1 As Double<BR>Dim dblTemp2 As Double<BR>Dim dblAng As Double<BR>Dim dblChord As Double<BR>Dim dblInclAng As Double<BR>Dim dblRad As Double<BR>Dim intDiv As Integer<BR>Dim houdian As Variant<BR>Dim houdian1(0 To 1) As Double<BR>Dim qiandian As Variant<BR>Dim qiandian1(0 To 1) As Double<BR>intDiv = 2<BR>varCords = objPline.Coordinates<BR>For Each varVert In varCords<BR>intVCnt = intVCnt + 1<BR>Next
For intCrdCnt = 0 To intVCnt / intDiv - 1<BR> If intCrdCnt < intVCnt / intDiv - 1 Then<BR> varCord = objPline.Coordinate(intCrdCnt)<BR> varNext = objPline.Coordinate(intCrdCnt + 1)<BR> ElseIf objPline.Closed Then<BR> varCord = objPline.Coordinate(intCrdCnt)<BR> varNext = objPline.Coordinate(0)<BR> Else<BR> Exit For<BR> End If<BR>dblXSl = (varCord(0) - varNext(0)) ^ 2<BR>dblYSl = (varCord(1) - varNext(1)) ^ 2<BR>houdian = objPline.Coordinate(intCrdCnt + 1)<BR>houdian1(0) = houdian(0): houdian1(1) = houdian(1)<BR>qiandian = objPline.Coordinate(intCrdCnt)<BR>qiandian1(0) = qiandian(0): qiandian1(1) = qiandian(1)<BR> <BR>If objPline.GetBulge(intCrdCnt) = 0 Then '当这段线是直线的时候<BR> Dim testdata As Double<BR> dblTemp = Sqr(dblXSl + dblYSl)<BR> dblTemp1 = disliangdian(p2(0), p2(1), qiandian1(0), qiandian1(1))<BR> dblTemp2 = disliangdian(p2(0), p2(1), houdian1(0), houdian1(1))<BR> disPtline = Sqr(dblTemp1 ^ 2 - ((dblTemp ^ 2 + dblTemp1 ^ 2 - dblTemp2 ^ 2) ^ 2) / (4 * dblTemp ^ 2))<BR> testdata = dblTemp ^ 2 + dblTemp1 ^ 2 - dblTemp2 ^ 2 '判断点与直线的关系,是不是在直线两个端点之间。<BR> <BR> If intCrdCnt = 0 Then '给最短距离一个初始化的值<BR> mindisPtline = dblTemp1<BR> End If<BR> <BR> If testdata < 0 Then '如果点在两个端点之外,距离为到端点距离的最小值<BR> disPtline = dblTemp1<BR> If dblTemp2 < dblTemp1 Then<BR> disPtline = dblTemp2<BR> End If<BR> End If<BR> MsgBox "这短直线中最短距离为: " & disPtline<BR> <BR> If disPtline < mindisPtline Then<BR> mindisPtline = disPtline<BR> End If<BR> <BR> MsgBox "目前最短距离为: " & mindisPtline<BR>Else '不是直线<BR> 'if there is a bulge we need to get an arc length<BR> dblChord = Sqr(dblXSl + dblYSl)<BR> dblInclAng = Atn(Abs(objPline.GetBulge(intCrdCnt))) * 4<BR> dblAng = (dblInclAng / 2) - ((Atn(1) * 4) / 2)<BR> dblRad = (dblChord / 2) / (Cos(dblAng))<BR> 'dblArc = dblInclAng * dblRad<BR> dblTemp1 = disliangdian(p2(0), p2(1), qiandian1(0), qiandian1(1))<BR> dblTemp2 = disliangdian(p2(0), p2(1), houdian1(0), houdian1(1))<BR> <BR> <BR> Dim fuzhuhu As AcadLWPolyline<BR> Dim fuzhuhu1(0 To 3) As Double<BR> Dim fuzhuhu2 As AcadArc<BR> Dim fuzhuhu3 As Variant<BR> Dim fuzhuhu4(0 To 2) As Double<BR> Dim fuzhuhu5 As Variant<BR> Dim qianangle As Double<BR> Dim houangle As Double<BR> Dim ceshidian As Variant
fuzhuhu1(0) = qiandian(0)<BR> fuzhuhu1(1) = qiandian(1)<BR> fuzhuhu1(2) = houdian(0)<BR> fuzhuhu1(3) = houdian(1)<BR> Set fuzhuhu = ThisDrawing.ModelSpace.AddLightWeightPolyline(fuzhuhu1)<BR> fuzhuhu.SetBulge 0, objPline.GetBulge(intCrdCnt)<BR> fuzhuhu5 = fuzhuhu.Explode<BR> If TypeOf fuzhuhu5(0) Is AcadArc Then<BR> Set fuzhuhu2 = fuzhuhu5(0)<BR> End If<BR> '确定弧的圆心<BR> fuzhuhu3 = fuzhuhu2.Center<BR> fuzhuhu4(0) = fuzhuhu3(0): fuzhuhu4(1) = fuzhuhu3(1): fuzhuhu4(2) = 0<BR> '确定弧的起始角度<BR> ceshidian = fuzhuhu2.StartPoint<BR> If Abs(ceshidian(0) - qiandian(0)) < zero1 And Abs(ceshidian(1) - qiandian(1)) < zero1 Then<BR> qianangle = fuzhuhu2.StartAngle<BR> houangle = fuzhuhu2.EndAngle<BR> Else<BR> qianangle = fuzhuhu2.EndAngle<BR> houangle = fuzhuhu2.StartAngle<BR> End If<BR> '删除辅助的圆弧<BR> fuzhuhu2.Delete<BR> fuzhuhu.Delete<BR> '判断点是不是在圆弧所在扇形区域内<BR> Dim fuzhuline As AcadLine<BR> Dim dblAngledian As Double<BR> Set fuzhuline = ThisDrawing.ModelSpace.AddLine(fuzhuhu4, p2)<BR> dblAngledian = fuzhuline.Angle<BR> <BR> disPtline = Abs(dblRad - fuzhuline.Length)<BR> If intCrdCnt = 0 Then '给最短距离一个初始化的值<BR> mindisPtline = dblTemp1<BR> End If<BR> fuzhuline.Delete<BR> '不在圆弧的扇形区域时的最短距离<BR> If (dblAngledian - qianangle) * (dblAngledian - houangle) > zero1 Then<BR> disPtline = dblTemp1<BR> If dblTemp2 < dblTemp1 Then<BR> disPtline = dblTemp2<BR> End If<BR> End If<BR> MsgBox "圆弧中最短长度是: " & disPtline<BR> '最短距离<BR> If disPtline < mindisPtline Then<BR> mindisPtline = disPtline<BR> End If<BR> MsgBox "目前最短距离为: " & mindisPtline<BR>End If
Next
MsgBox "最终最短距离为: " & mindisPtline<BR>End Sub<BR>
<FONT face=宋体 size=2>sorry!我的代码发现有问题了,主要是判断点在不在线段中间,和判断点在不在圆弧的扇形区域有问题,现改正了,测试没问题了!把它做成了函数,后面附了测试的代码:</FONT>
<FONT id=text3 style="FONT-SIZE: 10pt" face="宋体,verdana, arial, helvetica">Option Explicit<BR><BR>Public Function disPtLw(p1() As Double, aa As AcadEntity) As Double<BR>'先将直线、圆弧、圆都转化为多段线<BR>Dim mEntzhuan As AcadEntity<BR>Set mEntzhuan = aa<BR>Dim mLwlines As AcadLWPolyline '辅助的多段线,将所有的线都变成多段线<BR>If TypeOf mEntzhuan Is AcadLWPolyline Then<BR>Dim mfuzhuLw() As Object<BR>mfuzhuLw() = mEntzhuan.Offset(zero1)<BR>If TypeOf mfuzhuLw(0) Is AcadLWPolyline Then<BR>Set mLwlines = mfuzhuLw(0)<BR>End If<BR>ElseIf TypeOf mEntzhuan Is AcadArc Then<BR>Dim x As Double<BR>Dim hu2 As AcadArc<BR>Set hu2 = mEntzhuan<BR>x = Tan(hu2.TotalAngle / 4)<BR>ep(0) = hu2.StartPoint(0)<BR>ep(1) = hu2.StartPoint(1)<BR>ep(2) = hu2.EndPoint(0)<BR>ep(3) = hu2.EndPoint(1)<BR>Set mLwlines = ThisDrawing.ModelSpace.AddLightWeightPolyline(ep)<BR>mLwlines.SetBulge 0, x<BR>ElseIf TypeOf mEntzhuan Is AcadLine Then<BR>Dim zhi2 As AcadLine<BR>Set zhi2 = mEntzhuan<BR>ap(0) = zhi2.StartPoint(0)<BR>ap(1) = zhi2.StartPoint(1)<BR>ap(2) = zhi2.EndPoint(0)<BR>ap(3) = zhi2.EndPoint(1)<BR>Set mLwlines = ThisDrawing.ModelSpace.AddLightWeightPolyline(ap)<BR>ElseIf TypeOf mEntzhuan Is AcadCircle Then '对圆的处理<BR>Dim yp(0 To 5) As Double<BR>Dim yuan1 As AcadCircle<BR>Set yuan1 = mEntzhuan<BR>yp(0) = yuan1.Center(0) - yuan1.Radius<BR>yp(1) = yuan1.Center(1)<BR>yp(2) = yuan1.Center(0) + yuan1.Radius<BR>yp(3) = yuan1.Center(1)<BR>yp(4) = yuan1.Center(0) - yuan1.Radius<BR>yp(5) = yuan1.Center(1)<BR>Set mLwlines = ThisDrawing.ModelSpace.AddLightWeightPolyline(yp)<BR>mLwlines.SetBulge 0, 1<BR>mLwlines.SetBulge 1, 1<BR>Else<BR>MsgBox Err.Description<BR>Exit Function<BR>End If<BR><BR><BR><BR><BR>'对多段线来算最短距离<BR>Dim disPtline As Double<BR>Dim mindisPtline As Double<BR>Dim p2(0 To 2) As Double<BR>p2(0) = p1(0): p2(1) = p1(1): p2(2) = 0<BR>Dim objPline As AcadLWPolyline<BR>Set objPline = mLwlines<BR><BR>Dim intVCnt As Integer<BR>Dim varCords As Variant<BR>Dim varVert As Variant<BR>Dim varCord As Variant<BR>Dim varNext As Variant<BR>Dim intCrdCnt As Integer<BR>Dim dblXSl As Double<BR>Dim dblYSl As Double<BR>Dim dblZSl As Double<BR>Dim dblTemp As Double<BR>Dim dblTemp1 As Double<BR>Dim dblTemp2 As Double<BR>Dim dblAng As Double<BR>Dim dblChord As Double<BR>Dim dblInclAng As Double<BR>Dim dblRad As Double<BR>Dim intDiv As Integer<BR>Dim houdian As Variant<BR>Dim houdian1(0 To 1) As Double<BR>Dim qiandian As Variant<BR>Dim qiandian1(0 To 1) As Double<BR>intDiv = 2<BR>varCords = objPline.Coordinates<BR>For Each varVert In varCords<BR>intVCnt = intVCnt + 1<BR>Next<BR><BR>For intCrdCnt = 0 To intVCnt / intDiv - 1<BR>If intCrdCnt < intVCnt / intDiv - 1 Then<BR>varCord = objPline.Coordinate(intCrdCnt)<BR>varNext = objPline.Coordinate(intCrdCnt + 1)<BR>ElseIf objPline.Closed Then<BR>varCord = objPline.Coordinate(intCrdCnt)<BR>varNext = objPline.Coordinate(0)<BR>Else<BR>Exit For<BR>End If<BR>dblXSl = (varCord(0) - varNext(0)) ^ 2<BR>dblYSl = (varCord(1) - varNext(1)) ^ 2<BR>houdian = objPline.Coordinate(intCrdCnt + 1)<BR>houdian1(0) = houdian(0): houdian1(1) = houdian(1)<BR>qiandian = objPline.Coordinate(intCrdCnt)<BR>qiandian1(0) = qiandian(0): qiandian1(1) = qiandian(1)<BR><BR>If objPline.GetBulge(intCrdCnt) = 0 Then '当这段线是直线的时候<BR>Dim testdata As Double<BR>Dim testdata1 As Double<BR>dblTemp = Sqr(dblXSl + dblYSl)<BR>dblTemp1 = disliangdian(p2(0), p2(1), qiandian1(0), qiandian1(1))<BR>dblTemp2 = disliangdian(p2(0), p2(1), houdian1(0), houdian1(1))<BR>disPtline = Sqr(dblTemp1 ^ 2 - ((dblTemp ^ 2 + dblTemp1 ^ 2 - dblTemp2 ^ 2) ^ 2) / (4 * dblTemp ^ 2))<BR>testdata = Abs(dblTemp ^ 2 + dblTemp1 ^ 2 - dblTemp2 ^ 2) / (2 * dblTemp) '判断点与直线的关系,是不是在直线两个端点之间。<BR>testdata1 = Abs(dblTemp ^ 2 - dblTemp1 ^ 2 + dblTemp2 ^ 2) / (2 * dblTemp)<BR>If intCrdCnt = 0 Then '给最短距离一个初始化的值<BR>mindisPtline = dblTemp1<BR>End If<BR><BR>If testdata > dblTemp Or testdata1 > dblTemp Then '如果点在两个端点之外,距离为到端点距离的最小值<BR>disPtline = dblTemp1<BR>If dblTemp2 < dblTemp1 Then<BR>disPtline = dblTemp2<BR>End If<BR>End If<BR>'MsgBox "这段直线中最短距离为: " & disPtline<BR>If disPtline < mindisPtline Then<BR>mindisPtline = disPtline<BR>End If<BR>'MsgBox "目前最短距离为: " & mindisPtline<BR>Else '不是直线<BR>'if there is a bulge we need to get an arc length<BR>dblChord = Sqr(dblXSl + dblYSl)<BR>dblInclAng = Atn(Abs(objPline.GetBulge(intCrdCnt))) * 4<BR>dblAng = (dblInclAng / 2) - ((Atn(1) * 4) / 2)<BR>dblRad = (dblChord / 2) / (Cos(dblAng))<BR>'dblArc = dblInclAng * dblRad<BR>dblTemp1 = disliangdian(p2(0), p2(1), qiandian1(0), qiandian1(1))<BR>dblTemp2 = disliangdian(p2(0), p2(1), houdian1(0), houdian1(1))<BR><BR><BR>Dim fuzhuhu As AcadLWPolyline<BR>Dim fuzhuhu1(0 To 3) As Double<BR>Dim fuzhuhu2 As AcadArc<BR>Dim fuzhuhu3 As Variant<BR>Dim fuzhuhu4(0 To 2) As Double<BR>Dim fuzhuhu5 As Variant<BR>Dim qianangle As Double<BR>Dim houangle As Double<BR>fuzhuhu1(0) = qiandian(0)<BR>fuzhuhu1(1) = qiandian(1)<BR>fuzhuhu1(2) = houdian(0)<BR>fuzhuhu1(3) = houdian(1)<BR>Set fuzhuhu = ThisDrawing.ModelSpace.AddLightWeightPolyline(fuzhuhu1)<BR>fuzhuhu.SetBulge 0, objPline.GetBulge(intCrdCnt)<BR>fuzhuhu5 = fuzhuhu.Explode<BR>If TypeOf fuzhuhu5(0) Is AcadArc Then<BR>Set fuzhuhu2 = fuzhuhu5(0)<BR>End If<BR>'确定弧的圆心<BR>fuzhuhu3 = fuzhuhu2.Center<BR>fuzhuhu4(0) = fuzhuhu3(0): fuzhuhu4(1) = fuzhuhu3(1): fuzhuhu4(2) = 0<BR>'确定弧的起始角度<BR>qianangle = fuzhuhu2.StartAngle<BR>houangle = fuzhuhu2.EndAngle<BR>'删除辅助的圆弧<BR>fuzhuhu2.Delete<BR>fuzhuhu.Delete<BR>'判断点是不是在圆弧所在扇形区域内<BR>Dim fuzhuline As AcadLine<BR>Dim dblAngledian As Double<BR>Set fuzhuline = ThisDrawing.ModelSpace.AddLine(fuzhuhu4, p2)<BR>dblAngledian = fuzhuline.Angle<BR><BR>disPtline = Abs(dblRad - fuzhuline.Length)<BR>If intCrdCnt = 0 Then '给最短距离一个初始化的值<BR>mindisPtline = dblTemp1<BR>End If<BR>fuzhuline.Delete<BR>'不在圆弧的扇形区域时的最短距离<BR>If (dblAngledian - qianangle) * (dblAngledian - houangle) * (qianangle - houangle) < zero1 Then<BR>disPtline = dblTemp1<BR>If dblTemp2 < dblTemp1 Then<BR>disPtline = dblTemp2<BR>End If<BR>End If<BR>'MsgBox "圆弧中最短长度是: " & disPtline<BR>'最短距离<BR>If disPtline < mindisPtline Then<BR>mindisPtline = disPtline<BR>End If<BR>'MsgBox "目前最短距离为: " & mindisPtline<BR>End If<BR><BR>Next<BR>objPline.Delete<BR><BR>disPtLw = mindisPtline<BR>'MsgBox "最终最短距离为: " & mindisPtline<BR>End Function<BR><BR><BR><BR><BR><BR><BR>下面的是测试代码:<BR>Sub ztest()<BR>'点到多段线的最短距离<BR>Dim disPtline As Double<BR>Dim mindisPtline As Double<BR>Dim p1 As Variant<BR>Dim p2(0 To 1) As Double<BR>p1 = ThisDrawing.Utility.GetPoint(, " 请输入点:")<BR>p2(0) = p1(0): p2(1) = p1(1)<BR>Dim objPline As AcadLWPolyline<BR>Dim mlwlineqidian1 As AcadEntity<BR>ThisDrawing.Utility.GetEntity mlwlineqidian1, mlwlineqidian2, "请选择多段线"<BR>Dim x As Double<BR>x = disPtLw(p2, mlwlineqidian1)<BR>MsgBox "特斯他的长度为:" & x<BR>End Sub</FONT> <BR><BR><BR> 用Vlax类简单多了,还可求样条曲线的 运用中提示zero1未定义。 sorry zero1是我其他地方用的就是一个0.0000001之类的。这边好像可以用0代替!
另: <A name=17605><FONT color=#990000><B>lzh741206</B></FONT></A> 斑竹好:我的是CAD2002,用VBA但是里面好像没有VLAX类型库,请问哪里有?能给我一份吗??谢谢!QQ:5705560
E—mail:yujun821005@hotmail.com sorry,zero1是我在其他地方用到的,这边应该是用0。
另 <A name=17605><FONT color=#990000><B>lzh741206</B></FONT></A> 斑竹:你好!我用的是CAD2002。用VBA作的,但是我里面好像没有VLAX类型库for vBA,从哪里能下到,你能给我一份吗?谢谢!
qq:5705560 E-mail:yujun821005@hotmail.com 我觉得:可以直接用(斜率1*斜率2=-1) 算交点的办法,比你这个方法简单,我试过的
页:
[1]