yj821005 发表于 2005-3-17 15:09:00

[分享]给一个点和一段多段线,求出这个点到多段线的最短距离吗?

本帖最后由 作者 于 2005-3-22 16:53:12 编辑 <br /><br /> <FONT id=text1 style="FONT-SIZE: 10pt" face="宋体,verdana, arial, helvetica">[求助]有谁用VBA写过给一个点和一段多段线,求出这个点到多段线的最短距离吗?好写但是现在我还有其他的问题很忙,不晓得有没有哪位好心人写过(我觉得应该有人碰到过这个问题)</FONT> <BR>

yj821005 发表于 2005-3-22 09:55:00

自己写了,不晓得对不对!请明总看看,还有就是我的变量名字可能不是很规范!



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 &lt; 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 &lt; 0 Then                       '如果点在两个端点之外,距离为到端点距离的最小值<BR>                                                       disPtline = dblTemp1<BR>                                                                                       If dblTemp2 &lt; dblTemp1 Then<BR>                                                                                                                       disPtline = dblTemp2<BR>                                                                                       End If<BR>                       End If<BR>                       MsgBox "这短直线中最短距离为: " &amp; disPtline<BR>                       <BR>                       If disPtline &lt; mindisPtline Then<BR>                                                       mindisPtline = disPtline<BR>                       End If<BR>                                                       <BR>               MsgBox "目前最短距离为: " &amp; 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)) &lt; zero1 And Abs(ceshidian(1) - qiandian(1)) &lt; 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) &gt; zero1 Then<BR>                                                                                       disPtline = dblTemp1<BR>                                                                                       If dblTemp2 &lt; dblTemp1 Then<BR>                                                                                                                       disPtline = dblTemp2<BR>                                                                                       End If<BR>                                                       End If<BR>                                                               MsgBox "圆弧中最短长度是: " &amp; disPtline<BR>                                                       '最短距离<BR>                                                       If disPtline &lt; mindisPtline Then<BR>                                                                                       mindisPtline = disPtline<BR>                                                       End If<BR>                                                       MsgBox "目前最短距离为: " &amp; mindisPtline<BR>End If


Next


        MsgBox "最终最短距离为: " &amp; mindisPtline<BR>End Sub<BR>


yj821005 发表于 2005-3-24 09:58:00

<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 &lt; 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 &gt; dblTemp Or testdata1 &gt; dblTemp Then '如果点在两个端点之外,距离为到端点距离的最小值<BR>disPtline = dblTemp1<BR>If dblTemp2 &lt; dblTemp1 Then<BR>disPtline = dblTemp2<BR>End If<BR>End If<BR>'MsgBox "这段直线中最短距离为: " &amp; disPtline<BR>If disPtline &lt; mindisPtline Then<BR>mindisPtline = disPtline<BR>End If<BR>'MsgBox "目前最短距离为: " &amp; 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) &lt; zero1 Then<BR>disPtline = dblTemp1<BR>If dblTemp2 &lt; dblTemp1 Then<BR>disPtline = dblTemp2<BR>End If<BR>End If<BR>'MsgBox "圆弧中最短长度是: " &amp; disPtline<BR>'最短距离<BR>If disPtline &lt; mindisPtline Then<BR>mindisPtline = disPtline<BR>End If<BR>'MsgBox "目前最短距离为: " &amp; mindisPtline<BR>End If<BR><BR>Next<BR>objPline.Delete<BR><BR>disPtLw = mindisPtline<BR>'MsgBox "最终最短距离为: " &amp; 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 "特斯他的长度为:" &amp; x<BR>End Sub</FONT> <BR><BR><BR>

雪山飞狐_lzh 发表于 2005-3-24 17:53:00

用Vlax类简单多了,还可求样条曲线的

cqy 发表于 2005-3-31 14:16:00

运用中提示zero1未定义。

yj821005 发表于 2005-3-31 15:00:00

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

yj821005 发表于 2005-3-31 15:03:00

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

园子829 发表于 2005-3-31 23:12:00

我觉得:可以直接用(斜率1*斜率2=-1) 算交点的办法,比你这个方法简单,我试过的
页: [1]
查看完整版本: [分享]给一个点和一段多段线,求出这个点到多段线的最短距离吗?