平面圖樁號標註

平面圖樁號標註是平面圖的定線取完之後必經過程

生成流心的部分是透過設定取樣密度(流心連線距離),去抓兩個邊界的中心點連線取得中心點,再將收集到的中心點連線而成。

圖中的定線(紅色線段)可能是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



留言

  1. 大大您好,冒昧打擾您了,小的對這平面圖樁號標註很有興趣,也嘗試用幼幼班程度的語法弄了UI介面,但過程一直出錯,有點挫折,不知道大大方便可以分享這程式嗎? 在此萬分感謝

    回覆刪除
  2. 麻煩您了,這是小的信箱 cruisewing@gmail.com

    回覆刪除
  3. 你好,請問能否分享程式? 感激
    c194739@gmail.com

    回覆刪除

張貼留言

Popular Posts

Excel VBA @ 監造日報表、查驗表 -2

ExcelVBA@施工照片整理的應用範例

Excel VBA@ 監造日報表、查驗表