明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 8294|回复: 19

通过框选连接线的vba程序

  [复制链接]
发表于 2004-2-16 21:06:00 | 显示全部楼层 |阅读模式
  1. uniteSS为框选。uniteline为一根一根选择(只能选择两根)。对多段线和直线都有效。
复制代码
  1. Sub uniteSS()
  2.    'On Error Resume Next
  3.    Dim ssetObj As AcadSelectionSet
  4.    Set ssetObj = CreateSelectionSet("uniteSS")
  5.    Dim fType, fData
  6.    BuildFilter fType, fData, -4, "<or", 0, "line", 0, "LWPolyline", -4, "or>"
  7.    '屏选直线或多段线
  8.    ssetObj.SelectOnScreen fType, fData
  9.    Dim i As Integer
  10.    If ssetObj.Count <= 1 Then
  11.        ThisDrawing.Utility.Prompt "选择的线少于两个,退出命令。"
  12.        Exit Sub
  13.    End If
  14.    
  15.    Dim line1 As Object
  16.    Dim line2 As Object
  17.    
  18.    Set line1 = ssetObj(0)
  19.    Dim pd As Boolean
  20.    For i = 1 To ssetObj.Count
  21.        Set line2 = ssetObj(i)
  22.        '连接线
  23.        pd = unite2Line(line1, line2)
  24.        '如果连接不成功,则退出命令。
  25.        If Not pd Then ssetObj.Delete: Exit Sub
  26.    Next
  27.    ssetObj.Delete
  28. End Sub
  1. Sub uniteline()
  2.    On Error Resume Next
  3.    '取得线
  4.    Dim line1 As Object
  5.    Dim line2 As Object
  6.    Dim pt1, pt2, pt3, pt4, basePnt As AcadEntity
  7.    Dim lpt1, lpt2 As Variant
  8.    
  9.    gwGetEntity line1, basePnt, "请选择第一根直线或多段线:", "AcDbLine", "AcDbPolyline"
  10.    If line1 Is Nothing Then
  11.        ThisDrawing.Utility.Prompt "用户取消,退出命令。"
  12.        Exit Sub
  13.    End If
  14.    
  15.    gwGetEntity line2, basePnt, "请选择第二根直线或多段线:", "AcDbLine", "AcDbPolyline"
  16.    If line2 Is Nothing Then
  17.        ThisDrawing.Utility.Prompt "用户取消,退出命令。"
  18.        Exit Sub
  19.    End If
  20.    '连接线
  21.    unite2Line line1, line2
  22. End Sub
  1. Function unite2Line(ByRef line1 As Object, ByVal line2 As Object) As Boolean
  2.    '连接线函数,连接后的线返回到变量line1中,如果连接成功,unite2Line返回true,否则为false
  3.    On Error Resume Next
  4.    unite2Line = False
  5.    
  6.    If line1.Handle = line2.Handle Then
  7.        ThisDrawing.Utility.Prompt "选择的是同一直线或多段线,退出命令。"
  8.        Exit Function
  9.    End If
  10.    
  11.    getLinePoint line1, pt1, pt2
  12.    getLinePoint line2, pt3, pt4
  13.    
  14.    Dim A1, A2, A3 As Double
  15.    Dim maxdi As Double
  16.    A1 = ThisDrawing.Utility.AngleFromXAxis(pt1, pt2)
  17.    A2 = ThisDrawing.Utility.AngleFromXAxis(pt3, pt4)
  18.    A3 = ThisDrawing.Utility.AngleFromXAxis(pt1, pt3)
  19.    '判断四点是否共线
  20.    If Abs(A1 - A2) < 0.0000001 And (Abs(A1 - A3) < 0.0000001 Or Abs(Abs(A1 - A3) - PI) < 0.0000001) Then
  21.            '取得距离最远的两个点。
  22.            maxdi = MaxDouble(GetDistance(pt1, pt2), GetDistance(pt1, pt3), GetDistance(pt1, pt4), _
  23.                                                GetDistance(pt2, pt3), GetDistance(pt2, pt4), GetDistance(pt3, pt4))
  24.            If GetDistance(pt1, pt2) = maxdi Then lpt1 = pt1: lpt2 = pt2
  25.            If GetDistance(pt1, pt3) = maxdi Then lpt1 = pt1: lpt2 = pt3
  26.            If GetDistance(pt1, pt4) = maxdi Then lpt1 = pt1: lpt2 = pt4
  27.            If GetDistance(pt2, pt3) = maxdi Then lpt1 = pt2: lpt2 = pt3
  28.            If GetDistance(pt2, pt4) = maxdi Then lpt1 = pt2: lpt2 = pt4
  29.            If GetDistance(pt3, pt4) = maxdi Then lpt1 = pt3: lpt2 = pt4
  30.            '画直线
  31.            Select Case line1.ObjectName
  32.                  Case "AcDbLine"
  33.                      line1.StartPoint = lpt1
  34.                      line1.EndPoint = lpt2
  35.                      line2.Delete
  36.                      ThisDrawing.Utility.Prompt "线段已连接为直线."
  37.                      unite2Line = True
  38.                  Case "AcDbPolyline"
  39.                      Dim newPline As AcadLWPolyline
  40.                      Set newPline = AddLWPlineSeg(lpt1, lpt2, line1.ConstantWidth)
  41.                      newPline.Layer = line1.Layer
  42.                      newPline.color = line1.color
  43.                      newPline.Linetype = line1.Linetype
  44.                      line1.Delete
  45.                      line2.Delete
  46.                      Set line1 = newPline
  47.                      ThisDrawing.Utility.Prompt "线段已连接为多段线."
  48.                      unite2Line = True
  49.            End Select
  50.    Else: ThisDrawing.Utility.Prompt "两线不在同一直线上,退出命令."
  51.    End If
  52. End Function
 楼主| 发表于 2004-2-16 21:08:00 | 显示全部楼层
以下是上述代码调用的函数。
  1. '创建轻量多段线(只有两个顶点的直线多段线)
  2. Public Function AddLWPlineSeg(ByVal ptSt As Variant, ByVal ptEn As Variant, Optional ByVal width As Double = 0) As AcadLWPolyline
  3.        Dim objPline As AcadLWPolyline
  4.        Dim ptArr(0 To 3) As Double
  5.       
  6.        ptArr(0) = ptSt(0)
  7.        ptArr(1) = ptSt(1)
  8.        ptArr(2) = ptEn(0)
  9.        ptArr(3) = ptEn(1)
  10.       
  11.        Set objPline = ThisDrawing.ModelSpace.AddLightWeightPolyline(ptArr)
  12.        objPline.ConstantWidth = width
  13.        objPline.Update
  14.        Set AddLWPlineSeg = objPline
  15. End Function
  16. Public Function getLinePoint(ent As AcadEntity, ByRef Point1 As Variant, ByRef Point2 As Variant)
  17.          '本函数得到线的端点,其中point1为Y坐标较小的点
  18.        Dim p1(2) As Double
  19.        Dim p2(2) As Double
  20.        Dim k As Integer
  21.        On Error Resume Next
  22.                Select Case ent.ObjectName
  23.                        Case "AcDbLine"
  24.                                Point1 = ent.StartPoint
  25.                                Point2 = ent.EndPoint
  26.                                If ThisDrawing.Utility.AngleFromXAxis(Point1, Point2) >= PI Then
  27.                                        Point1 = ent.EndPoint
  28.                                        Point2 = ent.StartPoint
  29.                                End If
  30.                        Case "AcDbPolyline"
  31.                                Dim entCo As Variant
  32.                                entCo = ent.Coordinates
  33.                                k = UBound(entCo)
  34.                                If k >= 3 Then
  35.                                        p1(0) = entCo(0): p1(1) = entCo(1)
  36.                                        p2(0) = entCo(k - 1): p2(1) = entCo(k)
  37.                                        If ThisDrawing.Utility.AngleFromXAxis(p1, p2) >= PI Then
  38.                                                p2(0) = entCo(0): p2(1) = entCo(1)
  39.                                                p1(0) = entCo(k - 1): p1(1) = entCo(k)
  40.                                        End If
  41.                                        Point1 = p1: Point2 = p2
  42.                                End If
  43.                End Select
  44. End Function
  45. Public Function PI() As Double
  46.    PI = Atn(1) * 4
  47. End Function
  48. Public Sub GetEntityEx(ent As Object, pickedPoint, Optional Prompt)
  49.    '选择实体,直到用户取消操作
  50.        On Error Resume Next
  51. StartLoop:
  52.        ThisDrawing.Utility.GetEntity ent, pt, Prompt
  53.        If Err Then
  54.                If ThisDrawing.GetVariable("errno") = 7 Then
  55.                        Err.Clear
  56.                        GoTo StartLoop
  57.                Else
  58.                        Err.Raise vbObjectError + 5, , "用户取消操作"
  59.                End If
  60.        End If
  61. End Sub
  62. Public Sub gwGetEntity(ent As Object, pickedPoint, Prompt As String, ParamArray gType())
  63.   '选择某一类型的实体,如果选择错误则继续,按ESC退出
  64.   'gtype是实体名称,不区分大小写,可以用通配符号,如"AcDbBlockReference","acdb*text"等
  65.   Dim i As Integer
  66.   Dim pd As Boolean
  67.   pd = False
  68.   Do
  69.    GetEntityEx ent, pickedPoint, Prompt
  70.    
  71.    If ent Is Nothing Then
  72.        Exit Do
  73.    ElseIf UBound(gType) - LBound(gType) + 1 = 0 Then
  74.        Exit Do
  75.    Else
  76.        For i = LBound(gType) To UBound(gType)
  77.            If UCase(ent.ObjectName) Like UCase(gType(i)) Then
  78.                Exit Do
  79.            Else
  80.                pd = True
  81.            End If
  82.        Next i
  83.        If pd Then ThisDrawing.Utility.Prompt "选择的实体不符合要求."
  84.    End If
  85.   Loop
  86.   
  87. End Sub
  88. '计算两点之间距离
  89. Public Function GetDistance(sp As Variant, ep As Variant) As Double
  90.        Dim x As Double
  91.        Dim y As Double
  92.        Dim z As Double
  93.       
  94.        x = sp(0) - ep(0)
  95.        y = sp(1) - ep(1)
  96.        z = sp(2) - ep(2)
  97.       
  98.        GetDistance = Sqr((x ^ 2) + (y ^ 2) + (z ^ 2))
  99. End Function
  100. '返回两个Double类型变量的最大值
  101. Public Function MaxDouble(ByVal a As Double, ParamArray b()) As Double
  102.    MaxDouble = a
  103.    Dim i As Integer
  104.    For i = LBound(b) To UBound(b)
  105.        If b(i) > MaxDouble Then MaxDouble = b(i)
  106.    Next i
  107. End Function
  108. Public Function CreateSelectionSet(Optional ssName As String = "ss") As AcadSelectionSet
  109.    '返回一个空白选择集
  110.    
  111.        Dim ss As AcadSelectionSet
  112.       
  113.        On Error Resume Next
  114.        Set ss = ThisDrawing.SelectionSets(ssName)
  115.        If Err Then Set ss = ThisDrawing.SelectionSets.Add(ssName)
  116.        ss.Clear
  117.        Set CreateSelectionSet = ss
  118. End Function
  119. Public Sub BuildFilter(typeArray, dataArray, ParamArray gCodes())
  120.        '用数组方式填充一对变量以用作为选择集过滤器使用
  121.        Dim fType() As Integer, fData()
  122.        Dim index As Long, i As Long
  123.       
  124.        index = LBound(gCodes) - 1
  125.                
  126.        For i = LBound(gCodes) To UBound(gCodes) Step 2
  127.                index = index + 1
  128.                ReDim Preserve fType(0 To index)
  129.                ReDim Preserve fData(0 To index)
  130.                fType(index) = CInt(gCodes(i))
  131.                fData(index) = gCodes(i + 1)
  132.        Next
  133.        typeArray = fType: dataArray = fData
  134. End Sub
发表于 2004-2-16 21:20:00 | 显示全部楼层

好程序

好程序!
发表于 2004-2-16 21:31:00 | 显示全部楼层
干什么,抢生意啊??居然用我一样的名字??



这么长?看看在说,完了再完善完善俺的.


你的getLinePoint有漏洞,对于多端点的polyline没有判断是否为一直线,好像取得是第一个和最后一个端点的坐标,应该取最外侧端点的坐标.
 楼主| 发表于 2004-2-16 21:44:00 | 显示全部楼层
多交流交流,才能相互提高。我是参考着4楼的那个vba程序写的。所以就直接用了那个过程名。抱歉抱歉。



我对于多段线的顶点运算不是太熟悉,所以直接提取了起点和终点,最好应该是提取距离最远的两个顶点。





程序很长,不过下面的大部分函数都不是我写的,直接从明经中复制下来用。getLinePoint和MaxDouble在原来的基础上稍微改进了一下,以适合自己的要求。
发表于 2004-2-16 21:53:00 | 显示全部楼层

回复

无所谓吧!
发表于 2004-2-16 22:07:00 | 显示全部楼层
建议不要新建一个polyline,不然的话所有属性都要与第一根polyline相同(图层,颜色,宽度等等),比较麻烦,还是直接改第一根polyline的端点方便.
发表于 2004-2-16 22:46:00 | 显示全部楼层
不懂vba,不过看文字,实现这样的功能,用pedit/m不行么?
 楼主| 发表于 2004-2-17 09:13:00 | 显示全部楼层
mikewolf2k发表于2004-2-16 22:07:00建议不要新建一个polyline,不然的话所有属性都要与第一根polyline相同(图层,颜色,宽度等等),比较麻烦,还是直接改第一根polyline的端点方便.

多段线有时可能有好几个端点,我想在合并线的同时把线变成一根线,多段线就变成只有2个端点。
 楼主| 发表于 2004-2-17 09:18:00 | 显示全部楼层
无痕发表于2004-2-16 22:46:00不懂vba,不过看文字,实现这样的功能,用pedit/m不行么?
对于首尾衔接的线用pedit是可以的,但对于共线不相连的线就不行了。 在这个程序主要还是为了提高,其实已经有lisp的程序了。4楼的那个vba程序也可以用的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 13:43 , Processed in 0.181738 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表