平面圖樁號標註
平面圖樁號標註是平面圖的定線取完之後必經過程
'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