havano 发表于 2006-5-25 04:28:37

如何用VBA连接相邻的长折线?

已经醒了大约30个小时,我的项目越来越慢。我想我很快就会“睡觉”。我希望今天晚上醒来,找到以下问题的解决方案。
在一层上是一堆开放的LW折线。从视觉上看,它们形成了一个封闭的轮廓,因为它们的端点都相邻。该图层上没有其他东西,只有这个LW多段线的集合。
我需要知道这个轮廓的封闭区域。
一个普通的Autocad用户会选择修改-加入,选择一条多段线,然后用栅栏选择其他的,或者冻结所有其他图层,然后选择剩下的所有(Ctrl-A)。瞧,所有的多段线现在都是一条巨大的封闭多段线,其中的区域可以在属性窗口中找到。
我可以通过在VBA中使用send命令来模仿这样一个普通的Autocad用户,但老实说,我讨厌这样,它们会在你最意想不到的时候咬你。我也可以使用算术。形状是一堆参数化建模例程的副产品,这是我之前完成的程序的一部分,所以我也许可以通过“回溯”这些例程来收集必要的信息。
但我相信你们中的一个人有一个使用干净VB(A)的简单解决方案,所以当我醒来时,我会有一些期待,并且能够在本周末的某个时候完成d***项目,至少是具有挑战性的部分。
现在是上午10点30分,我又开始看到眼角的那些小动作。睡觉时间!在声音开始之前......:丑陋:
**** Hidden Message *****

havano 发表于 2006-5-25 06:45:43

不错的功能Jürg

Bryco 发表于 2006-5-25 11:05:16

(哎呀,我在完成之前就发布了我的回复!这是最终版本。)
我总是羡慕那些只需阅读音符就能“听到”音乐的音乐家。同样使用VBA,我可能永远不会达到那种水平的监视。所以我花了一些时间来“听到你的代码的音乐”。用我简单的话来说,我发现它的作用是:
检查您呈现的两条折线是否可以连接。如果是这样,请将第二个的顶点等添加到第一个,删除第二个并报告“任务完成!我加入了两个折线”。
所以,现在,所需要的只是一个嵌入例程:
创建一个要研究的折线选择集
-比较/连接集合中的第一个与所有其他的(使用您的函数)
-在所有比较之后,如果可能,与第一个连接,刷新选择集
-执行新运行,另一个(或使用递归或嵌套循环),直到只剩下一个折线或无法进行进一步的连接
然后关闭此折线并获取我需要的区域值。(除此之外,这幅画已经被清理了一些,但是无知的观众看不到区别。)
谢谢尤尔格!与此同时,我为我的问题找到了一个更简单的解决方案(今天早上我昏昏欲睡,看不见它),但我认为许多其他读者很可能会利用你的杰作!

Bryco 发表于 2006-5-25 13:32:39

像这样的东西应该可以工作
Sub JoininJoininJoinin()
'Get them plines joinin'
'This song is quite anoyin'
'raw code
Dim objSelSet As AcadSelectionSet
Dim objSelSets As AcadSelectionSets
Dim intGroup(0 To 1) As Integer
Dim varData(0 To 1) As Variant
Dim intcnt As Integer
Set objSelSets = ThisDrawing.SelectionSets
For Each objSelSet In objSelSets
If objSelSet.Name = "PolyJoin" Then
    objSelSets.Item(objSelSet.Name).Delete
    Exit For
End If
Next objSelSet
intGroup(0) = 0: varData(0) = "LWPolyline": intGroup(1) = 8: varData(1) = "LayerName"
Set objSelSet = objSelSets.Add("PolyJoin")
objSelSet.Select acSelectionSetAll, , , intGroup, varData
For intcnt = 1 To objSelSet.Count - 1
MeJoinPline objSelSet.Item(0), objSelSet.Item(intcnt), 0.01
Next intcnt
End Sub

Bryco 发表于 2006-5-25 15:39:17

仔细想想,只有当它们在选择集中都按顺序排列时,它才起作用。如果它们不按顺序排列,很可能,它不会连接所有的东西。您可以将选择集分解为一个函数,填充它,运行连接函数,重新填充选择集,然后循环,直到选择集计数= 1。不过要打个勾,因为如果他们中的任何一个不在你的模糊因素之内,不能加入,你就会永远循环下去。

Bryco 发表于 2006-5-25 16:21:25

我已经为此工作了2年,它的99.5%,其中一些3D有点棘手。我为cnc画了很多,所以我不想要额外的顶点或线。这应该删除坏蛋。至于应该加入什么,你必须做出决定。我不知道我是否应该先把所有的线都做成多边形。我很确定我可以在这里消除一些步骤,但是越来越难看到树木的觅食。

Option Explicit
Declare Function GetCursor Lib "user32" () As Long
Public Declare Function GetAsyncKeyState Lib "user32" _
      (ByVal vKey As Long) As Integer
Public Declare Sub CopyMemory Lib "kernel32" _
    Alias "RtlMoveMemory" _
    (dest As Any, source As Any, ByVal Length As Long) 'AlmostEqual
Private DeleteCol As Collection
Private StartEndCol As Collection
Private SlopeCol As Collection
Private CoordList As Collection
Private Const PolyClosedFudge As Double = 0.005
'If the first coordinate and last coordinate are within this distance
'The poly will be closed.
Const Pi As Double = 3.14159265358979
Public Property Get CurrentSpace() As AcadBlock
If ThisDrawing.GetVariable("CVPORT") = 1 Then
    Set CurrentSpace = ThisDrawing.PaperSpace
Else
    Set CurrentSpace = ThisDrawing.ModelSpace
End If
End Property
'Aims
'1) To select a group of lines,arcs and polys
'and create clean polys w/ no double ups
'or double points.
'2) Delete unnecessary geometry
'Some will want to add a layer control here.
'3) Note 2d and 3dpolys are not included
'4) I have used line formulas rather than polar angles
'hoping that it will be faster.
Sub VBAPLJoin()
    'On Error GoTo Err_Control
    Dim oLine As AcadLine
    Dim LineCol As New Collection
    Dim oPline As AcadLWPolyline
    Dim CoordsCt As Integer
    Dim oArc As AcadArc
    Dim oSSets As AcadSelectionSets
    Dim ss As AcadSelectionSet
    Dim FilterType(6) As Integer
    Dim FilterData(6) As Variant
    Dim i As Integer, j As Integer, k As Integer
    Dim intNotParallel As Integer
    Dim PtsCount As Integer, Count As Integer
    Dim StartPt As Variant, EndPt As Variant
    Dim StartP(2) As Double, EndP(2) As Double
    Dim Pt As Variant
    Dim pts() As Double
    Dim SE(4) As Variant
    Dim obj(0) As AcadEntity
    Dim M As Double, OrigY As Double
    Dim UcsNormal As Variant, N As Variant
    Dim blnRemove As Boolean
    Dim dblElev As Double
    Dim strlayer As String
    Dim util As AcadUtility
    PtsCount = 1
    Set util = ThisDrawing.Utility
    Set StartEndCol = New Collection
      
    'Stage 1Create the selectionset
    Set oSSets = ThisDrawing.SelectionSets
    For Each ss In oSSets
      If ss.Name = "SS" Then
            ss.Delete
            Exit For
      End If
    Next
    Set ss = oSSets.Add("SS")
   
   
    FilterType(0) = 0: FilterData(0) = "Line,Arc,LWPolyline"
    FilterType(1) = -4: FilterData(1) = ""
    FilterType(6) = -4: FilterData(6) = "NOT>"
   
   Do ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      ss.SelectOnScreen FilterType:=FilterType, FilterData:=FilterData
    Loop Until GetCursor = 0
   
    If ss.Count > 500 Then
      MsgBox "You have selected " & ss.Count & " objects. Please select less :"
      Exit Sub
    End If
    If ss.Count = 0 Then
      Set ss = Nothing
      ''''''''''''MsgBox "Nothing selected."
      Exit Sub
    End If
    If ss.Count = 1 Then
      If TypeOf ss(0) Is AcadLWPolyline Then
            Set oPline = ss(0)
            If UBound(oPline.Coordinates) = 3 Then
                Exit Sub
            End If
      End If
    End If
    UcsNormal = CurrentUcsNormal
    'We're using the SS set index to keep track of the objects
    'So first pass is just to clean up the set
    'From then on the order wont change
   
    'Stage 2- delete zero length ents, remove non applicable ents
   For i = ss.Count - 1 To 0 Step -1
      If TypeOf ss(i) Is AcadLine Then
            Set oLine = ss(i)
            If oLine.Length0 Then
      CheckLines LineCol 'Sub checks for equal, overlapping lines
    End If
    If ss.Count = 0 Then 'items may have been removed
      Exit Sub
    End If
    If intNotParallel = 1 Then
      MsgBox intNotParallel & " object was not parallel to the current UCS."
    ElseIf intNotParallel > 1 Then
      MsgBox intNotParallel & " objects were not parallel to the current UCS."
    End If
   
    'Stage 5
    'This function sorts the start and end points into order
    If StartEndCol.Count > 1 Then
      SortPts
    End If
   
    Dim blnClosed As Boolean, blnNewLine As Boolean
    Dim BulgeCol() As Double, PolyBulgeCol() As Double
    Dim MPt(2) As Double, Seg As Double, Ht As Double
    Dim sPt, ePt
    ReDim pts(1)
AddNewLine:
   
    Count = StartEndCol.Count
    j = 0
    If Count > 1 Then
      For i = 1 To Count
            If StartEndCol(i)(2) = "NewLine" Then
                j = i - 1
                Exit For
            End If
      Next
      If j = 0 Then j = Count
      If EqualPts(StartEndCol(1)(0), StartEndCol(j)(1)) Then
            blnClosed = True
      End If
    End If
   
    N = ss(StartEndCol(1)(2)).Normal
    dblElev = ElevationFromPt(StartEndCol(1)(0), N) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    strlayer = ss(StartEndCol(1)(2)).Layer
    'Stage 6
    'Draw a pline for each set of continuous points
    'NewLine signifies there are no more points to add
    'to the last poly so a new poly is reqd.
   
   
    sPt = StartEndCol(1)(0)
    sPt = util.TranslateCoordinates(sPt, acWorld, acOCS, 1, N)
    pts(0) = sPt(0)
    pts(1) = sPt(1)
    PtsCount = 1
    For i = 1 To StartEndCol.Count
      If StartEndCol(i)(2) = "NewLine" Then
            StartEndCol.Remove i
            blnNewLine = True
            Exit For
      End If
      
      If TypeOf ss(StartEndCol(i)(2)) Is AcadArc Then
            Set oArc = ss(StartEndCol(i)(2))
            ePt = StartEndCol(i)(1)
            ePt = util.TranslateCoordinates(ePt, acWorld, acOCS, 1, N)
                     
            ReDim Preserve pts(PtsCount + 2)
            pts(PtsCount + 1) = ePt(0)
            pts(PtsCount + 2) = ePt(1)
            'Now get the bulge
            sPt = ToUcs(oArc.Startpoint): ePt = ToUcs(oArc.Endpoint)
            Dim CPt As Variant
            CPt = ToUcs(oArc.Center)
            MPt(0) = sPt(0) + ((ePt(0) - sPt(0)) / 2)
            MPt(1) = sPt(1) + ((ePt(1) - sPt(1)) / 2)
            MPt(2) = sPt(2)
            Seg = (Length(sPt, ePt)) / 2
            If oArc.TotalAngle > Pi Then
                Ht = (2 * oArc.radius) - (oArc.radius - Length(CPt, MPt))
            Else
                Ht = oArc.radius - Length(CPt, MPt)
            End If
            ReDim Preserve BulgeCol((PtsCount - 1) / 2)
             If EqualPts(oArc.Startpoint, StartEndCol(i)(0)) Then
            
                BulgeCol((PtsCount - 1) / 2) = Ht / Seg 'Bulge
            Else
                BulgeCol((PtsCount - 1) / 2) = -Ht / Seg
                           
            End If
            PtsCount = PtsCount + 2
            StartEndCol.Remove i
            i = i - 1
            GoTo Skip3
      End If
      If TypeOf ss(StartEndCol(i)(2)) Is AcadLine Then
PlineLine:
            ePt = StartEndCol(i)(1)
            ePt = util.TranslateCoordinates(ePt, acWorld, acOCS, 1, N)
            'addpt EPt, , 2
            ReDim Preserve pts(PtsCount + 2)
            pts(PtsCount + 1) = ePt(0)
            pts(PtsCount + 2) = ePt(1)
            ReDim Preserve BulgeCol((PtsCount - 1) / 2)
            BulgeCol((PtsCount - 1) / 2) = 0
            PtsCount = PtsCount + 2
            StartEndCol.Remove i
            i = i - 1
            GoTo Skip3
      End If
      If TypeOf ss(StartEndCol(i)(2)) Is AcadLWPolyline Then
            Set oPline = ss(StartEndCol(i)(2))
            CoordsCt = (UBound(oPline.Coordinates) - 1) / 2
            If CoordsCt = 1 Then
                If oPline.GetBulge(0) = 0 Then
                  GoTo PlineLine
                End If
            End If
            Dim Coord, coords()
            ReDim coords(CoordsCt)
            ReDim PolyBulgeCol(CoordsCt - 1)
            For j = 0 To 1
                StartPt(j) = oPline.Coordinates(j)
            Next j
            StartPt(2) = oPline.Elevation
            Pt = util.TranslateCoordinates(StartPt, acOCS, acWorld, 1, oPline.Normal)
            If Not EqualPts(Pt, StartEndCol(i)(0)) Then 'swap''''''''''''''''''
                k = 0
                For j = CoordsCt To 0 Step -1
                  coords(k) = oPline.Coordinate(j)
                  k = k + 1
                Next
                k = 0
                For j = CoordsCt - 1 To 0 Step -1
                  PolyBulgeCol(k) = -oPline.GetBulge(j)
                  k = k + 1
                Next
            Else
                For j = 0 To CoordsCt
                  coords(j) = oPline.Coordinate(j)
                Next
                For j = 0 To CoordsCt - 1
                  PolyBulgeCol(j) = oPline.GetBulge(j)
                Next
               
            End If
            ReDim Preserve pts(PtsCount + (CoordsCt * 2))
            For j = 1 To CoordsCt 'We already have the first pair
            
                pts(PtsCount + 1) = coords(j)(0)
                pts(PtsCount + 2) = coords(j)(1)
                ReDim Preserve BulgeCol((PtsCount - 1) / 2)
                BulgeCol((PtsCount - 1) / 2) = PolyBulgeCol(j - 1)
                PtsCount = PtsCount + 2
            Next
            StartEndCol.Remove i
            i = i - 1
            GoTo Skip3
      End If
Skip3:
      If StartEndCol.Count = 0 Then
            Exit For
      End If
    Next i
   
   
    If blnClosed Then
      ReDim Preserve pts(PtsCount - 2)
    End If
   
    Set oPline = ThisDrawing.ModelSpace.AddLightWeightPolyline(pts)
    oPline.Elevation = dblElev
    'oPline.Normal = N ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    'oPline.Color = acMagenta
    oPline.Layer = strlayer
    For i = 0 To UBound(BulgeCol)
      oPline.SetBulge i, BulgeCol(i)
    Next
    If blnClosed Then
      oPline.Closed = True
    Else
      PolyVertexCheck oPline ''''''''''''''''''''''''''''''''''
    End If
   
   
    If blnNewLine Then
      blnNewLine = False
      blnClosed = False
      If StartEndCol.Count > 0 Then
            GoTo AddNewLine
      End If
    End If
   
    ss.Erase 'Delete the selection set leaving us w/ nice new polys
    ss.Delete
Exit_Here:
    Exit Sub
Err_Control:
    Select Case Err.Number
    'Add your Case selections here
      Case Else
      MsgBox Err.Description
      Err.Clear
      Resume Exit_Here
    End Select
End Sub

Jeff_M 发表于 2006-5-25 16:44:06

一些函数
Function GetSlope(DeltaX, DeltaY, StartPt As Variant, _
                M As Double, OrigY As Double) As Integer
    DeltaX = CDbl(DeltaX)
    DeltaY = CDbl(DeltaY)
    If Rd(DeltaY, 0) Then   'Line is horizontal
      M = 0
      OrigY = StartPt(1)
      GetSlope = 0
    ElseIf Rd(DeltaX, 0) Then'Line is vertical
      M = StartPt(0)
      OrigY = 0
      GetSlope = 1
    Else
      M = DeltaY / DeltaX
      OrigY = StartPt(1) - (M * StartPt(0))
      GetSlope = 2
    End If
End Function
Private Function SortPts()
   
    Dim A As Variant, b As Variant
    Dim StartPt As Variant, EndPt As Variant
    Dim NextStartPt As Variant, NextEndPt As Variant
    Dim NewStartEndCol As New Collection
    Dim blnRemoved As Boolean
    Dim intBefore As Integer
    Dim i As Integer
   
    intBefore = 1
    A = StartEndCol(1)
    StartPt = A(0): EndPt = A(1)
    NewStartEndCol.Add A
    StartEndCol.Remove 1
    Do While StartEndCol.Count > 0
Removed:
      blnRemoved = False
      For i = StartEndCol.Count To 1 Step -1
            
            NextStartPt = StartEndCol(i)(0)
            NextEndPt = StartEndCol(i)(1)
            
            If EqualPts(StartPt, NextStartPt) Then
                StartPt = NextEndPt
                A = StartEndCol(i)
                'swap start and end points
                A(0) = NextEndPt
                A(1) = NextStartPt
                NewStartEndCol.Add A, , intBefore
                blnRemoved = True
                GoTo skip
            End If
            If EqualPts(StartPt, NextEndPt) Then
                StartPt = NextStartPt
                A = StartEndCol(i)
                NewStartEndCol.Add A, , intBefore
                blnRemoved = True
                GoTo skip
            End If
            If EqualPts(EndPt, NextStartPt) Then
                EndPt = NextEndPt
                A = StartEndCol(i)
                NewStartEndCol.Add A
                blnRemoved = True
                GoTo skip
            End If
            If EqualPts(EndPt, NextEndPt) Then
                  EndPt = NextStartPt
                  A = StartEndCol(i)
                  'swap start and end points
                  A(0) = NextEndPt
                  A(1) = NextStartPt
                  NewStartEndCol.Add A
                  blnRemoved = True
                  GoTo skip
            End If
            
skip:
            If blnRemoved Then
                StartEndCol.Remove i
                GoTo Removed
            End If
      Next
      
      If blnRemoved = False Then
            If StartEndCol.Count > 0 Then
                A(2) = "NewLine"
                NewStartEndCol.Add A
                A = StartEndCol(1)
                StartPt = A(0): EndPt = A(1)
                NewStartEndCol.Add A
                intBefore = NewStartEndCol.Count
                StartEndCol.Remove 1
            End If
         End If
    Loop
      
   
    For i = 1 To NewStartEndCol.Count
      StartEndCol.Add NewStartEndCol(i)
    Next
End Function

'Rules used
'1)identical-
'   delete one
'2)line within line-and no arms off the smaller-delete smaller
      'if within has arm and the larger doesn't-remove the larger
      'intWithin 1=start equal,2=end equal,3=neither
'3)Overlapping
    'if no arms off the inside pts then delete both, add one long line
    'intWithin=4
Private Sub CheckLines(LineCol As Collection)
    Dim oLine As AcadLine
    Dim SiAs Variant, SjAs Variant, varSEAs Variant
    Dim blnSti As Boolean, blnStj As Boolean
    Dim blnEndi As Boolean, blnEndj As Boolean
    Dim Starti As Variant, Endi As Variant
    Dim Startj As Variant, Endj As Variant
    Dim i As Integer, j As Integer, k As Integer
    Dim intWithin As Integer '1=start equal,2=end equal,3=neither
    Dim blnRemoved As Boolean
    Dim intVertical As Integer
   
    For i = LineCol.Count To 1 Step -1 'allows removal from set
      Si = LineCol(i)
      Starti = Si(0): Endi = Si(1)
      'now do the expensive point checks we will need to
      'check if a line has an arm coming off it
      'we only want to do this once
      blnSti = PtCheck(Starti, i)
      blnEndi = PtCheck(Endi, i)
      For j = LineCol.Count To 1 Step -1
            blnRemoved = False
            If Not j = i Then
                If Rd(LineCol(j)(4), LineCol(i)(4)) Then 'Check origY values
                  If Rd(LineCol(j)(3), LineCol(i)(3)) Then'Check slope values
                  'Check z values''''''''''''''''''''''''''''''''
                        Sj = LineCol(j)
                        Startj = Sj(0): Endj = Sj(1)
            
                        'now we dont have to factor in Line direction
                        'Make i the most left or the lowest
                        If Startj(0)Endi(0) Or Startj(1) > Endi(1) Then
                            GoTo skip 'Get it the next time
                        End If
                     
                        'Check for identical
                        If Rd(Startj(0), Starti(0)) And Rd(Endj(0), Endi(0)) Then   'Could be vertical
                            If Rd(Startj(1), Starti(1)) Then
                              If Rd(Endj(1), Endi(1)) Then   'identical
                                    DeleteIt LineCol, j
                                    blnRemoved = True
                                    'i = i - 1
                                    GoTo skip
                                 End If
                            End If
                        End If
      
                        intWithin = 0
                        intVertical = 0
                        'Check for within or overlapping
                        'Do the verticals first
                        If Rd(Startj(0), Starti(0)) And Rd(Endj(0), Endi(0)) Then'vertical now
                            intVertical = 1
                            If Rd(Startj(1), Starti(1)) Then
                              intWithin = 1
                            End If
                            If Startj(1) > Starti(1) Then
                              If Endj(1)i Then ''''''''''''''''
                                                j = j - 1
                                          End If
                                          DeleteIt LineCol, j
                                          LineCol.Add Si
                                          StartEndCol.Add Si
                                          'i = i - 1
                                          GoTo skip
                                        End If
                                    End If
                              End If
                            End If
                            GoTo BranchControl
                        End If
                              
                        'Now horiz. lines and the rest
                        If Rd(Startj(0), Starti(0)) Then
                            intWithin = 1
                            GoTo BranchControl
                        End If
                        
                        If Startj(0) > Starti(0) Then
                            If Endj(0)i Then
                                          j = j - 1
                                        End If
                                        DeleteIt LineCol, j
                                        LineCol.Add Si
                                        StartEndCol.Add Si
                                        'i = i - 1
                                        GoTo skip
                                    End If
                              End If
                            End If
                        End If
                        
                        If intWithin = 0 Then GoTo skip
               
BranchControl:
                        'now do the expensive point checks we will need to
                        'check if a line has an arm coming off it
                        'we only want to do this once
                        blnStj = PtCheck(Startj, j)
                        blnEndj = PtCheck(Endj, j)
   
                        If intWithin = 4 Then 'overlapping
                            If Not blnStj And Not blnEndi Then 'make one line
                              Si = LineCol(i)
                              Si(1) = Endj
                              DeleteIt LineCol, i
                              blnRemoved = True
                              If j > i Then ''''''''''''''''
                                    j = j - 1
                              End If
                              DeleteIt LineCol, j
                              LineCol.Add Si
                              StartEndCol.Add Si
                              'i = i - 1
                              GoTo skip
                            End If
                        End If
                        
                        If intWithin = 1 Then
                            If Endj(intVertical)i Then
                j = j - 1
            End If
            If i > j Then
                i = i - 1
            End If
      End If
      Next j
    Next i

End Sub
Private Sub DeleteIt(COL As Collection, i As Integer)
    'Add layermanagement here if you need it.
    Dim k As Integer
    For k = 1 To StartEndCol.Count
      If StartEndCol(k)(2) = COL(i)(2) Then
            StartEndCol.Remove k
            Exit For
      End If
    Next
    COL.Remove i
End Sub
Function SortStartEnd(StartPt, EndPt)
    Dim varPt As Variant
    If EndPt(0) - StartPt(0) > 0.00000001 Then
    'If StartPt(0)EndPt(1) Then
               varPt = StartPt
               StartPt = EndPt
               EndPt = varPt
            Else
                Exit Function
            End If
      Else
            varPt = StartPt
            StartPt = EndPt
            EndPt = varPt
      End If
    End If
End Function
Function CurrentUcsNormal() As Variant
    Dim UcsX, UcsY, UcsZ(2) As Double
    UcsX = ThisDrawing.GetVariable("Ucsxdir")
    UcsY = ThisDrawing.GetVariable("Ucsydir")
    'get CrossProduct
    UcsZ(0) = UcsX(1) * UcsY(2) - UcsX(2) * UcsY(1)
    UcsZ(1) = UcsX(2) * UcsY(0) - UcsX(0) * UcsY(2)
    UcsZ(2) = UcsX(0) * UcsY(1) - UcsX(1) * UcsY(0)
    CurrentUcsNormal = UcsZ
    'Debug.Print UcsZ(0), UcsZ(1), UcsZ(2)
End Function
Function ToUcs(Pt As Variant) As Variant
    ToUcs = ThisDrawing.Utility.TranslateCoordinates(Pt, acWorld, acUCS, False)
End Function
Function ToWcs(Pt As Variant) As Variant
    ToWcs = ThisDrawing.Utility.TranslateCoordinates(Pt, acUCS, acWorld, False)
End Function
Function Rd(num1 As Variant, num2 As Variant) As Boolean
    Dim dRet As Double
    dRet = num1 - num2
    If Abs(dRet)2 Or i0 Then
            Stx = Startpoint(0): Sty = Startpoint(1)
            Enx = Endpoint(0): Eny = Endpoint(1)
            dX = Stx - Enx
            dY = Sty - Eny
            If i = 1 Then
                Length = Sqr(dX * dX + dY * dY)
            Else
                Stz = Startpoint(2): Enz = Endpoint(2)
                dZ = Stz - Enz
                Length = Sqr((dX * dX) + (dY * dY) + (dZ * dZ))
            End If
      Else
            Exit Function
      End If
    Else
      Exit Function
    End If
End Function
Function ElevationFromPt(Pt As Variant, varNormal As Variant) As Double
    'Ax+ By + Cz + d = 0 formula for a plane where d=-oLWP.Elevation
    'ElevationFromPt = Pt(0) * UcsNormal(0) + Pt(1) * UcsNormal(1) + Pt(2) * UcsNormal(2)
    ElevationFromPt = (Pt(0) * varNormal(0)) + (Pt(1) * varNormal(1)) + (Pt(2) * varNormal(2))
End Function

Bryco 发表于 2006-5-25 20:38:10

这个是棘手的
Function PolyVertexCheck(oPline As AcadLWPolyline, Optional j As Integer = -1) As Boolean
    'Checks for duplicate verticies
    'Should be closed.
    'Some Double backs
    Dim cCount As Integer
    Dim Dist As Double
    Dim NewCoordList As New Collection
    Dim i As Integer, k As Integer
    Dim Coord As Variant, PrevCoord As Variant, coord2 As Variant
    Dim Coord3 As Variant, Coord4 As Variant
    Dim SlopeCol As New Collection
    Dim BulgeCol As New Collection
    Dim DeltaX As Double, DeltaY As Double
    Dim StartPt As Variant
    Dim M As Double, OrigY As Double
    Dim Slopes(3) As Double
    Dim intXY As Integer
    Dim Rem1 As Integer, Rem2 As Integer
    Dim intSlope As Integer
    Dim obj(0) As AcadEntity
    Dim ss As AcadSelectionSet
    Dim blnBeginning As Boolean
    Dim blnRemoved As Boolean
   
    cCount = (UBound(oPline.Coordinates) - 1) / 2
   
    NewCoordList.Add (0)
    For i = 1 To cCount
      Coord = oPline.Coordinate(i): PrevCoord = oPline.Coordinate(i - 1)
      'Here we check for two equal verticies. Dont add them if they are equal.
      If Rd(Coord(0), PrevCoord(0)) And Rd(Coord(1), PrevCoord(1)) Then GoTo skip
            
      DeltaX = Coord(0) - PrevCoord(0): DeltaY = Coord(1) - PrevCoord(1)
      Slopes(2) = GetSlope(DeltaX, DeltaY, PrevCoord, M, OrigY)
      Slopes(0) = M: Slopes(1) = OrigY
      Slopes(3) = oPline.GetBulge(i - 1)
      SlopeCol.Add Slopes
      k = i
      NewCoordList.Add (k)
skip:
    Next
      
    cCount = NewCoordList.Count
    Debug.Print cCount
    If cCount = 1 Then 'zero length pline
      Set ss = ThisDrawing.SelectionSets("SS")
      If j > -1 Then
            Set obj(0) = ss(j)
            ss.RemoveItems obj
      End If
      oPline.Delete
      PolyVertexCheck = False
      Exit Function '''''
    End If
BeginCheck:
   If cCount > 2 Then
      If SlopeCol.Count = 2 Then
      'check for unneeded middle point in a straigth line
            If SlopeCol(1)(3)0 Then GoTo Skip2
            If SlopeCol(2)(3)0 Then GoTo Skip2
            If Rd(SlopeCol(1)(0), SlopeCol(2)(0)) Then
                If Rd(SlopeCol(1)(1), SlopeCol(2)(1)) Then
                  Coord = oPline.Coordinate(0)
                  coord2 = oPline.Coordinate(1)
                  Coord3 = oPline.Coordinate(2)
                  If EqualPts(Coord, Coord3) Then
                        NewCoordList.Remove cCount
                        GoTo Skip2
                  End If
                  intSlope = SlopeCol(1)(2)
                  If intSlope = 1 Then
                        intXY = 1'vertical
                  Else
                        intXY = 0
                  End If
                  
                  If Coord(intXY) > coord2(intXY) Then
                        If coord2(intXY) > Coord3(intXY) Then
                            NewCoordList.Remove 2
                        Else
                            If Coord(intXY) > Coord3(intXY) Then
                              NewCoordList.Remove 3
                            Else
                              NewCoordList.Remove 1
                            End If
                        End If
                  Else
                        If Coord(intXY) > Coord3(intXY) Then
                              NewCoordList.Remove 1
                        Else
                            If Coord3(intXY) > coord2(intXY) Then
                              NewCoordList.Remove 2
                            Else
                              NewCoordList.Remove 3
                            End If
                        End If
                  End If
                End If
            End If
      Else
            For i = cCount To 3 Step -1
                'check for unneeded middle point in a straigth line
                If oPline.GetBulge(i - 1)0 Then GoTo Skipi
                If oPline.GetBulge(i - 2)0 Then GoTo Skipi
                If Rd(SlopeCol(i - 1)(0), SlopeCol(i - 2)(0)) Then
                  If Rd(SlopeCol(i - 1)(1), SlopeCol(i - 2)(1)) Then
                        Coord = oPline.Coordinate(NewCoordList(i))
                        coord2 = oPline.Coordinate(NewCoordList(i - 1))
                        Coord3 = oPline.Coordinate(NewCoordList(i - 2))
                        If Rd(Coord(0), coord2(0)) Then 'vertical
                            intXY = 1
                        Else
                            intXY = 0
                        End If
         
   
                         If i = cCount Then 'Double back at end
                            If Coord(intXY) > Coord3(intXY) Then
                              If Coord(intXY)coord2(intXY) Then
                                    NewCoordList.Remove (i)
                                    SlopeCol.Remove i - 1
                                    blnRemoved = True
                                    GoTo Skipi ''''''''''''''''''
                              End If
                            End If
                        End If
                        
                        If i - 3 = 0 Then 'Double back at beginning
                            If Coord(intXY) > coord2(intXY) Then
                              If Coord(intXY) > Coord3(intXY) Then
                                    If Coord3(intXY) > coord2(intXY) Then
                                        NewCoordList.Remove (1)
                                        SlopeCol.Remove 1
                                        blnBeginning = True
                                        blnRemoved = True
                                        GoTo Skipi ''''''''''''''''''
                                    End If
                              End If
                            Else
                              If Coord(intXY)coord2(intXY) Then
                            If coord2(intXY) > Coord3(intXY) Then
                              NewCoordList.Remove (i - 1)
                              SlopeCol.Remove i - 2
                              blnRemoved = True
                              GoTo Skipi ''''''''''''''''''
                            End If
                        Else
                            If coord2(intXY)2 Then
                cCount = NewCoordList.Count
                For i = cCount To 4 Step -1
                  If oPline.GetBulge(i - 1)0 Then GoTo Skip2i
                  If oPline.GetBulge(i - 2)0 Then GoTo Skip2i
                  If oPline.GetBulge(i - 3)0 Then GoTo Skip2i
                  If oPline.GetBulge(i - 4)0 Then GoTo Skip2i
                  'Not checking for arc double backs as they are so rare.
                  intSlope = SlopeCol(i - 1)(2)
                  If Not intSlope = SlopeCol(i - 2)(2) Then GoTo Skip2i
                  If Not intSlope = SlopeCol(i - 3)(2) Then GoTo Skip2i
                  If intSlope = 0 Then intXY = 0'horiz
                  If intSlope = 1 Then intXY = 1'vertical
                  If intSlope = 2 Then
                        intXY = 2 ''''''''''''''''''''''2-15
                        If Rd(SlopeCol(i - 1)(0), SlopeCol(i - 2)(0)) Then
                            If Rd(SlopeCol(i - 2)(0), SlopeCol(i - 3)(0)) Then
                              If Rd(SlopeCol(i - 1)(1), SlopeCol(i - 2)(1)) Then
                                    If Rd(SlopeCol(i - 2)(1), SlopeCol(i - 3)(1)) Then
                                        intXY = 0
                                    'Else: GoTo Skip2i ''''''''''''''''''''''''''
                                    End If
                              End If
                            End If
                        End If
                  End If
                  
                  If intXY > 1 Then GoTo Skip2i
                                    
   
                  Coord = oPline.Coordinate(NewCoordList(i - 3))
                  coord2 = oPline.Coordinate(NewCoordList(i - 2))
                  Coord3 = oPline.Coordinate(NewCoordList(i - 1))
                  Coord4 = oPline.Coordinate(NewCoordList(i))
                  If Rd(Coord(0), coord2(0)) Then 'vertical
                        intXY = 1
                  Else
                        intXY = 0
                  End If
                  Rem1 = -1: Rem2 = -1
                  'code for double backs''''''''''''''''''''''''''''''
                  If Coord(intXY)Coord(intXY) Then
                                    Rem1 = i - 1: Rem2 = i - 2
                              Else
                                    Rem1 = i - 2: Rem2 = i - 3
                              End If
                            End If
                        Else
                            If Coord3(intXY) > Coord(intXY) Then
                              Rem1 = i: Rem2 = i - 1
                            Else
                              Rem1 = i: Rem2 = i - 3
                            End If
                        End If
                  Else
                        If coord2(intXY) > Coord4(intXY) Then
                            If Coord3(intXY) > coord2(intXY) Then
                              If Coord3(intXY)-1 Then
                        NewCoordList.Remove Rem1
                        SlopeCol.Remove Rem1 - 1
                        i = i - 1
                  End If
                  If Rem2 > -1 Then
                        NewCoordList.Remove Rem2
                        'i = i - 1
                        If Rem2 > 1 Then
                            SlopeCol.Remove Rem2 - 1
                        Else
                            SlopeCol.Remove Rem2
                        End If
                  End If
            
                     
Skip2i:
            Next i
      End If
    End If
End If
Skip2:
   
   
   
    Dim NewPline As AcadLWPolyline
    Dim Cwidth As Double
    Dim blnNonConstantWidth As Boolean
   
    On Error Resume Next
    Cwidth = oPline.ConstantWidth
    If Err.Description = "Invalid input" Then
      blnNonConstantWidth = True
      Err.Clear
    End If
    On Error GoTo 0
   
    'check for should be closed
    If oPline.Closed = False Then
       Dim X1 As Double, Y1 As Double
       Dim X2 As Double, Y2 As Double
       Dim blnClosed As Boolean
       X1 = oPline.Coordinate(NewCoordList(1))(0)
       Y1 = oPline.Coordinate(NewCoordList(1))(1)
       X2 = oPline.Coordinate(NewCoordList(NewCoordList.Count))(0)
       Y2 = oPline.Coordinate(NewCoordList(NewCoordList.Count))(1)
       If Fuzzed(X1, X2, PolyClosedFudge) Then
         If Fuzzed(Y1, Y2, PolyClosedFudge) Then
               NewCoordList.Remove (NewCoordList.Count)
               blnClosed = True
         End If
       End If
    End If
    If Not NewCoordList.Count - 1 = (UBound(oPline.Coordinates) - 1) / 2 Then
      Dim PtsCount As Integer
      PtsCount = (NewCoordList.Count * 2) - 1
      Dim pts() As Double
      ReDim pts(PtsCount) As Double
      cCount = NewCoordList.Count
      For i = 1 To cCount
            k = (i - 1) * 2
            pts(k) = oPline.Coordinate(NewCoordList(i))(0)
            pts(k + 1) = oPline.Coordinate(NewCoordList(i))(1)
      Next
      
      
      Set NewPline = CurrentSpace.AddLightWeightPolyline(pts)
      If oPline.Closed = True Then
            NewPline.Closed = True
      End If
      With NewPline
            .Color = oPline.Color
            .Elevation = oPline.Elevation
            .Layer = oPline.Layer
            .LineType = oPline.LineType
            .LinetypeGeneration = oPline.LinetypeGeneration
            .LineWeight = oPline.LineWeight
            .Normal = oPline.Normal
            .Thickness = oPline.Thickness
            If Cwidth > 0 Then
                .ConstantWidth = Cwidth
            End If
            On Error GoTo 0
            
      End With
      'For i = 1 To NewCoordList.Count
      For i = 1 To SlopeCol.Count
            k = i - 1
            NewPline.SetBulge k, SlopeCol(i)(3)
            If blnNonConstantWidth Then
                Dim StartWidth As Double, endWidth As Double
                oPline.GetWidth NewCoordList(i), StartWidth, endWidth
                NewPline.SetWidth k, StartWidth, endWidth
            End If
      Next
      
      If j = -1 Then
            oPline.Delete
            Set oPline = NewPline
      Else
            Set ss = ThisDrawing.SelectionSets("SS")
            Set obj(0) = ss(j)
            ss.RemoveItems obj
            oPline.Delete
            Set oPline = NewPline
            If blnClosed = True Then
                oPline.Closed = True
            Else
                Set obj(0) = oPline
                ss.AddItems obj
            End If
      End If
      oPline.Update
    End If
   PolyVertexCheck = True
End Function

Bryco 发表于 2006-5-25 20:42:04

哦,他们看起来太久了,每个人在到达这里之前都会睡着。

Bryco 发表于 2006-5-25 20:44:09

你有展示你的代码所做的例子的图像吗?
谢谢。
页: [1] 2
查看完整版本: 如何用VBA连接相邻的长折线?