平面圖樁號標註
平面圖樁號標註是平面圖的定線取完之後必經過程
'clsCL
生成流心的部分是透過設定取樣密度(流心連線距離),去抓兩個邊界的中心點連線取得中心點,再將收集到的中心點連線而成。
圖中的定線(紅色線段)可能是AcadPolyline或者是AcadLWPolyline
兩者的差別僅在於Coordinates是否有Z值
大致上概念是將該多段線先任取兩點取得其"方位角"再用方位角+90度與方位角-90度取出橫斷面樁兩端點,再進行後續處理。
程式碼的概念都是幾何關係,滿滿的都是包括極坐標轉XY、方位角轉正角,XY轉方位角
有興趣者請參考以下程式碼~
UI介面:
圖面成果:
| 我比較偏愛這款(右樁標註+左樁標註+方向旗標) | 
程式碼:
'clsCL
Private CAD As New clsACAD
Private Math As New clsMath
Private arrLen() As Variant
Private arrLoc() As Variant
Private collCLPt As New Collection
Private CL As Object
Private BL As Object
Private pts As Variant
Private CO As Byte
Private totalLen As Double
Public w As Double
Public nowLoc As Double
Public IsLeftShow As Boolean
Public IsRightShow As Boolean
Public NeedBox As Boolean
Public NeedDir As Boolean
Public BLnext As Double
Const WIDTH_COE = 1.2
Private Sub Class_Initialize()
Set lay = CAD.acaddoc.Layers.Add("橫斷面樁")
lay.color = 4 'acCyan
Set lay = CAD.acaddoc.Layers.Add("中心樁")
lay.color = 1 'acRed
On Error Resume Next
CAD.acaddoc.Linetypes.Load "CENTER", "acad.lin"
lay.linetype = "CENTER"
End Sub
Sub CrossLine_Main()
Dim nextL As Double
Dim storeLen As Double
IsFirst = True
'Call getCenterLine(pts, CO, totalLen)
'Call getLoc(totalLen)
k = 1
nextL = arrLen(0)
For i = 0 To UBound(pts) - CO Step CO
    X0 = pts(i): Y0 = pts(i + 1)
    X1 = pts(i + CO): Y1 = pts(i + 1 + CO)
    ptLen = Sqr((X1 - X0) ^ 2 + (Y1 - Y0) ^ 2)  '兩點距
    fi = Math.getAz(X0, Y0, X1, Y1)
    
    If IsFirst Then
    
        MyLoc = Format(nowLoc + 0, "0K+000")
        Call DrawCrossLine(X0, Y0, fi, MyLoc)
        IsFirst = False
    
    End If
    
    sumLen = sumLen + ptLen
    If sumLen <= nextL Then storeLen = storeLen + ptLen '不夠用先存起來
    Do Until sumLen <= nextL
        
        moveL = nextL
        
        If storeLen <> 0 Then moveL = nextL - storeLen: storeLen = 0
        sumLen = sumLen - nextL
        If k <= UBound(arrLen) Then nextL = arrLen(k) '下一單距
        
        dx = Math.degcos(fi) * (moveL)
        dy = Math.degsin(fi) * (moveL)
        
        Xnow = X0 + dx: Ynow = Y0 + dy
        X0 = Xnow: Y0 = Ynow
        
        MyLoc = arrLoc(k - 1)
        
        Call DrawCrossLine(X0, Y0, fi, MyLoc)
        k = k + 1
    
    Loop
    storeLen = sumLen
    
Next
MyLoc = Format(nowLoc + totalLen, "0K+000")
Call DrawCrossLine(X1, Y1, fi, MyLoc)
End Sub
Sub getCenterLine() 'pts, CO, totalLen)
If CL Is Nothing Then
    
    Set sset = CAD.CreateSSET("CL")
    Set CL = sset(0)
    CL.Layer = "中心樁"
    
End If
pts = CL.Coordinates
totalLen = CL.Length
CO = 3
If TypeName(CL) = "IAcadLWPolyline" Then CO = 2
End Sub
Sub DrawCrossLine(ByVal X0 As Double, ByVal Y0 As Double, ByVal fi As Double, ByVal MyLoc As String)
CAD.acaddoc.ActiveLayer = CAD.acaddoc.Layers("橫斷面樁")
Dim spt(2) As Double
Dim ept(2) As Double
spt(0) = X0 + Math.degcos(fi + 90) * w
spt(1) = Y0 + Math.degsin(fi + 90) * w
ept(0) = X0 + Math.degcos(fi - 90) * w
ept(1) = Y0 + Math.degsin(fi - 90) * w
Set lineObj = CAD.AddLine(spt, ept)
If NeedDir Then
    Call DrawDirection(spt, fi, -w / 16, w / 10)
    Call DrawDirection(ept, fi, w / 16, w / 10)
End If
Call CAD.SetXdataToObj(lineObj, Replace(MyLoc, "K", ""))
If IsRightShow Then Call DrawCrossLoc(X0, Y0, MyLoc, fi, 90, 1)
If IsLeftShow Then Call DrawCrossLoc(X0, Y0, MyLoc, fi, -90, 3)
End Sub
Private Sub DrawDirection(dpt, fi, dx, dy)
Dim spt(2) As Double
Dim Tri As Object
Dim vertices(4 * 3 - 1) As Double
X = dpt(0): Y = dpt(1)
vertices(0) = X: vertices(1) = Y
vertices(3) = X: vertices(4) = Y + dy 'w / 5
vertices(6) = X + dx: vertices(7) = Y
vertices(9) = X: vertices(10) = Y
Set Tri = CAD.AddPolyLine(vertices)
Tri.rotate dpt, Math.deg2rad(-fi)
Call CAD.Hatch(Tri, 1, "SOLID")
End Sub
Private Sub DrawCrossLoc(X0, Y0, MyLoc, fi, ByVal rotangle As Double, ByVal alignmode As Byte)
Dim tept(2) As Double
tept(0) = X0 + Math.degcos(fi + rotangle) * w * WIDTH_COE
tept(1) = Y0 + Math.degsin(fi + rotangle) * w * WIDTH_COE
Set txtobj = CAD.AddMixText(MyLoc, tept, w / 5, alignmode)
If NeedBox Then Set boxobj = CAD.AddTextBox(txtobj)
txtobj.rotate tept, Math.deg2rad(-fi)
If NeedBox Then boxobj.rotate tept, Math.deg2rad(-fi)
End Sub
Sub getLoc() 'ByVal totalLen As Double)
Dim sumLen As Double
Dim c As Integer
IsAsk = True
Do While sumLen < totalLen
    If IsAsk = True Then
        nextLen = InputBox("起始樁號為 " & Format(0, "0+000") & vbNewLine & _
                            "結束樁號為 " & Format(nowLoc + totalLen, "0+000") & vbNewLine & _
                             "請輸入下一樁的單距,目前為" & Format(nowLoc + sumLen, "0+000"))
    End If
    
    If nextLen Like "*-" Then
        nextLen = Val(Left(nextLen, Len(nextLen) - 1)): IsAsk = False
    Else
        nextLen = Val(nextLen)
    End If
    sumLen = sumLen + nextLen
    
    ReDim Preserve arrLoc(c)
    ReDim Preserve arrLen(c)
    
    arrLen(c) = nextLen
    arrLoc(c) = Format(nowLoc + sumLen, "0K+000")
    
    c = c + 1
Loop
End Sub
Sub getLocXLS()
Dim collmyloc As New Collection
Set sht = Sheets("土方")
With sht
    lr = .Cells(Rows.Count, 1).End(xlUp).Row
    For r = 2 To lr
        collmyloc.Add Math.TranLoc(.Cells(r, 1))
    Next
End With
nowLoc = collmyloc(1)
For i = 1 To collmyloc.Count - 1
    ReDim Preserve arrLoc(i - 1)
    ReDim Preserve arrLen(i - 1)
    Interval = collmyloc(i + 1) - collmyloc(i)
    sumInterval = sumInterval + Interval
    arrLen(i - 1) = Interval
    arrLoc(i - 1) = Format(nowLoc + sumInterval, "0K+000")
Next
    
End Sub
Sub BorderLine_Main()
Dim nextL As Double
Dim storeLen As Double
IsFirst = True
Call getBorderLine(pts, CO, totalLen)
k = 1
nextL = BLnext
For i = 0 To UBound(pts) - CO Step CO
    X0 = pts(i): Y0 = pts(i + 1)
    X1 = pts(i + CO): Y1 = pts(i + 1 + CO)
    ptLen = Sqr((X1 - X0) ^ 2 + (Y1 - Y0) ^ 2)  '兩點距
    fi = Math.getAz(X0, Y0, X1, Y1)
    
    If IsFirst Then
    
        Call getCLpt(X0, Y0, fi): IsFirst = False
    
    End If
    
    sumLen = sumLen + ptLen
    If sumLen <= nextL Then storeLen = storeLen + ptLen '不夠用先存起來
    Do Until sumLen <= nextL
        
        moveL = nextL
        
        If storeLen <> 0 Then moveL = nextL - storeLen: storeLen = 0
        sumLen = sumLen - nextL
        'If k <= UBound(arrLen) Then nextL = arrLen(k) '下一單距
        
        dx = Math.degcos(fi) * (moveL)
        dy = Math.degsin(fi) * (moveL)
        
        Xnow = X0 + dx: Ynow = Y0 + dy
        X0 = Xnow: Y0 = Ynow
        
        Call getCLpt(X0, Y0, fi)
        k = k + 1
    
    Loop
    storeLen = sumLen
    
Next
MyLoc = Format(nowLoc + totalLen, "0K+000")
Call getCLpt(X1, Y1, fi)
End Sub
Sub getCLpt(ByVal X As Double, ByVal Y As Double, ByVal fi As Double)
Dim spt(2) As Double
Dim ept(2) As Double
Dim midpt(2) As Double
spt(0) = X + Math.degcos(fi + 90)
spt(1) = Y + Math.degsin(fi + 90)
ept(0) = X + Math.degcos(fi - 90)
ept(1) = Y + Math.degsin(fi - 90)
Set CrossLine = CAD.AddLine(spt, ept)
On Error Resume Next
retpt1 = CrossLine.IntersectWith(CL, acExtendThisEntity)
retpt2 = CrossLine.IntersectWith(BL, acExtendThisEntity)
midpt(0) = (retpt1(0) + retpt2(0)) / 2
midpt(1) = (retpt1(1) + retpt2(1)) / 2
If midpt(0) <> 0 Then collCLPt.Add midpt
CrossLine.Delete
End Sub
Private Sub getBorderLine(pts, CO, tl)
Set sset = CAD.CreateSSET("CL")
Set CL = sset(0)
pts = CL.Coordinates
tl = CL.Length
CO = 3
If TypeName(CL) = "IAcadLWPolyline" Then CO = 2
Set sset = CAD.CreateSSET("BL")
Set BL = sset(0)
End Sub
Sub DrawCenterLine()
Dim vertices() As Double
ReDim vertices(3 * collCLPt.Count - 1)
For i = 1 To collCLPt.Count
    pt = collCLPt.Item(i)
    
    vertices(3 * (i - 1)) = pt(0)
    vertices(3 * (i - 1) + 1) = pt(1)
Next
Set CL = CAD.AddPolyLine(vertices)
CL.Layer = "中心樁"
End Sub
 
大大您好,冒昧打擾您了,小的對這平面圖樁號標註很有興趣,也嘗試用幼幼班程度的語法弄了UI介面,但過程一直出錯,有點挫折,不知道大大方便可以分享這程式嗎? 在此萬分感謝
回覆刪除麻煩您留下信箱與我聯繫,謝謝
刪除麻煩您了,這是小的信箱 cruisewing@gmail.com
回覆刪除你好,請問能否分享程式? 感激
回覆刪除c194739@gmail.com