通過autoCAD-vba畫管道單線圖 [ v1.7 ]

更新版本v1.7:

1、代碼重構。終於抽出時間。

2、[v1.7] v - 表示閥門,後跟兩個焊口號,以逗號分隔,閥門只支持6個方位,即fblrud


' list.txt

m,100,100,100
NumPos=b
b,ZQ3-YJ03-D114-1.2-1+2W
uv,ZQ3-YJ03-N1-D114-1.2-3F,ZQ3-YJ03-N1-D114-1.2-4F
b,ZQ3-YJ03-D114-1.2-1+5W
' ==========================
' 功能:根據list.txt內容繪製單選圖
' 版本:v1.7
' 作者:[email protected] #bin.xu
' 時間:2018-06-04
'
' 0、字母說明:
'    m: 起始座標
'    u: 向上
'    d: 向下
'             f:前(北)
'                |
'    l:左(西)  ──├── r:右(東)
'                |
'             b:後(南)
'
' 1、功能說明:
'    1.1、字母后跟線段長度的整數倍(<10),缺省時爲1個線段長度
'    1.2、[v1.5] 支持空間方位,如lfu,表示左前上方
'    1.3、[v1.5] 支持單引號註釋,單行或語句後方
'    1.4、[v1.5] 自動保存上次使用路徑
'    1.5、[v1.6] 單行NumPos=f, 設置編號顯示在圓點的哪個方位,
'                取值:f,b,l,r(前,後,左,右)其中一個
'                作用範圍:直到下一個NumPos賦值,               左前右對齊
'    1.6、[v1.6] 編號前加f=,設置編號顯示在圓點的哪個方位,
'                取值:f,b,l,r(前,後,左,右)其中一個
'                作用範圍:當前語句,
'                優先級:高於NumPos
'    1.7、[v1.7] v - 表示閥門,後跟兩個焊口號,以逗號分隔
'                閥門只支持6個方位,即fblrud
'
' 2、例:
'    m,100,100,100                 ' 起始座標
'    f,ZQ2-YJxx-D114-abdc-1        ' 向前畫1個單位長度線段,
'                                  ' 並標註焊口爲ZQ2-YJxx-D114-abdc-1
'    r,ZQ2-YJxx-D114-abdc-5w
'    f2                            ' 向前畫2個單位長度線段
'    l,ZQ2-YJxx-D114-abdc-6
'    lfu,ZQ2-YJxx-D114-abdc-7      ' 左前上方畫線
'    f,f=ZQ3-YJ01-N1-D114-3.4-77Z  ' 編號在圓點的前方標註
'    NumPos=l                      ' 之後的編號在圓點左側標註
'    fv,ZQ3-YJ03-N1-D114-1.2-3F,ZQ3-YJ03-N1-D114-1.2-4F   ' 閥門
'
' ==========================

Sub main()
    Dim ret
    Dim strListFile As String
    
    ret = fn_setFont("txt.shx")
    strListFile = fn_getListPath("~setting.tmp")
    ret = fn_anayleFile(strListFile)
    ThisDrawing.Regen True
    ' 西南等軸側
    ThisDrawing.SendCommand "-view" & vbCr & "swiso" & vbCr
    ZoomAll
End Sub


' /////////////////////////////////////
Function fn_setFont(strFont As String)
    ' 設置字體文件
    fn_setFont = 0
    Dim newFontFile As String
    Dim textStyle1 As AcadTextStyle
    Set textStyle1 = ThisDrawing.ActiveTextStyle
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set sh = CreateObject("WScript.Shell")
    newFontFile = Application.Path & "\Fonts\" & strFont
    textStyle1.Height = 10
    If fso.FileExists(newFontFile) Then
        textStyle1.fontFile = newFontFile
    End If
    fn_setFont = -1
End Function


' /////////////////////////////////////
Function fn_getListPath(strFileName As String)
    ' 獲取list.txt文件路徑,並保存
    fn_getListPath = 0
    
    Dim strListFilePath As String
    Dim strTmpPath As String
    Dim strListFile As String
    Dim sh, fso
    
    Set sh = CreateObject("WScript.Shell")
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    strListFilePath = ""
    
    ' 獲取~setting.tmp文件
    strTmpPath = sh.ExpandEnvironmentStrings("%TMP%")
    strTmpPath = strTmpPath & "\" & strFileName
    If fso.FileExists(strTmpPath) Then
        Open strTmpPath For Input As #1
        Do While Not EOF(1)
            Line Input #1, rLine
            strListFilePath = CStr(rLine)
        Loop
        Close #1
    End If
    
    ' 獲取list.txt路徑
    strListFilePath = InputBox("請輸入《list.txt》文件路徑", "輸入", strListFilePath)
    strListFile = Replace(strListFilePath, """", "") & "\list.txt"
    
    ' 路徑寫入~setting.tmp文件
    If fso.FileExists(strListFile) Then
        Open strTmpPath For Output As #1
            Write #1, Replace(strListFilePath, """", "")
        Close #1
    End If
    
    fn_getListPath = strListFile
End Function


' /////////////////////////////////////
Function fn_anayleFile(strFileName As String)
    
    fn_anayleFile = 0
    
    Dim ret_xyz(0 To 2) As Double
    Dim strNumPos As String
    Dim listFile As String
    Dim rLine As String
    Dim arr_xyz                  ' split(str,",")
    Dim ret
    Dim fso
    
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    ret_xyz(0) = 0: ret_xyz(1) = 0: ret_xyz(2) = 0
    strNumPos = "f"
    listFile = strFileName
    
    ' 分析文件內容
    If fso.FileExists(listFile) Then
        Open listFile For Input As #1
        Do While Not EOF(1)
            Line Input #1, rLine
            rLine = Trim(rLine)
            ' 排除註釋行、空行
            If Mid(rLine, 1, 1) <> "'" And CStr(rLine) <> "" Then
                ' 去除後方註釋內容
                If InStr(rLine, "'") <> 0 Then
                    rLine = Trim(Mid(rLine, 1, InStr(rLine, "'") - 1))
                End If
                
                If LCase(Mid(rLine, 1, 1)) = "m" Then
                    ' 起始座標
                    arr_xyz = Split(rLine, ",")
                    ret_xyz(0) = arr_xyz(1)
                    ret_xyz(1) = arr_xyz(2)
                    ret_xyz(2) = arr_xyz(3)
                ElseIf LCase(Mid(rLine, 1, 6)) = "numpos" Then
                    ' 編號顯示方位
                    strNumPos = Mid(StrReverse(rLine), 1, 1)
                    If InStr(strNumPos, "f") = 0 And _
                       InStr(strNumPos, "b") = 0 And _
                       InStr(strNumPos, "l") = 0 And _
                       InStr(strNumPos, "r") = 0 Then
                       strNumPos = "f"
                    End If
                Else
                    ret = fn_drawObject(ret_xyz, rLine, strNumPos)
                    ret_xyz(0) = ret(0)
                    ret_xyz(1) = ret(1)
                    ret_xyz(2) = ret(2)
                End If
            End If
        Loop
        Close #1
    End If
    ThisDrawing.Regen True
    fn_anayleFile = -1
End Function


' /////////////////////////////////////
Function fn_drawObject(xyz0() As Double, strstr As String, strNumPos As String)
    ' 畫實例,包含線,實心圓,編號
    fn_drawObject = 0
    
    Dim arrStr
    Dim strFirstSec As String
    Dim strDirection As String
    Dim iMul As Integer
    Dim strTextPos As String
    Dim strText As String
    
    strTextPos = strNumPos
    
    ' 分析單行
    arrStr = Split(strstr, ",")
    strFirstSec = CStr(Trim(arrStr(0)))
    ' 畫線方向
    If IsNumeric(Mid(StrReverse(strFirstSec), 1, 1)) = True Then
        strDirection = LCase(Mid(strFirstSec, 1, Len(strFirstSec) - 1))
    Else
        strDirection = LCase(strFirstSec)
    End If
    ' 倍數
    iMul = 1
    If Len(strFirstSec) > 1 And IsNumeric(Mid(StrReverse(strFirstSec), 1, 1)) = True Then
        iMul = CInt(Mid(StrReverse(strFirstSec), 1, 1))
    End If
    ' 編號及方向
    strText = Mid(strstr, InStr(strstr, ",") + 1)
    strText = Replace(Trim(strText), " ", "")
    If InStr(arrStr(1), "=") <> 0 Then
        strTextPos = Mid(strText, 1, 1)
        strText = Mid(strText, 3)
    End If
    
    If InStr(strFirstSec, "v") <> 0 Then
        ' 畫閥門
        fn_drawObject = fn_drawValve(xyz0, iMul, strDirection, strText, strTextPos)
    Else
        ' 畫線段
        fn_drawObject = fn_drawPloyline(xyz0, iMul, strDirection, strText, strTextPos)
    End If
End Function


' /////////////////////////////////////
Function fn_drawPloyline(xyz0() As Double, iMul As Integer, strDirection As String, strText As String, strTextPos As String)
    fn_drawPloyline = 0
    
    Dim xyz1(0 To 2) As Double
    Dim xyz(0 To 5) As Double
    Dim xyzText(0 To 2) As Double
    Dim iLen As Integer
    Dim objPL As Acad3DPolyline
    Dim color As New AcadAcCmColor
    
    xyz1(0) = xyz0(0)
    xyz1(1) = xyz0(1)
    xyz1(2) = xyz0(2)
    iLen = 80              ' 線段默認長度
    iLen = iMul * iLen
    color.SetRGB 0, 255, 255
    
    If InStr(strDirection, "f") <> 0 Then xyz1(1) = xyz0(1) + iLen
    If InStr(strDirection, "b") <> 0 Then xyz1(1) = xyz0(1) - iLen
    If InStr(strDirection, "l") <> 0 Then xyz1(0) = xyz0(0) - iLen
    If InStr(strDirection, "r") <> 0 Then xyz1(0) = xyz0(0) + iLen
    If InStr(strDirection, "u") <> 0 Then xyz1(2) = xyz0(2) + iLen
    If InStr(strDirection, "d") <> 0 Then xyz1(2) = xyz0(2) - iLen
    
    xyz(0) = xyz0(0): xyz(1) = xyz0(1): xyz(2) = xyz0(2)
    xyz(3) = xyz1(0): xyz(4) = xyz1(1): xyz(5) = xyz1(2)
    
    ' 畫線
    Set objPL = ThisDrawing.ModelSpace.Add3DPoly(xyz)
    objPL.Lineweight = acLnWt030      ' 線寬
    objPL.TrueColor = color           ' 顏色
    
    ' 中間點座標
    xyzText(0) = (xyz0(0) + xyz1(0)) / 2
    xyzText(1) = (xyz0(1) + xyz1(1)) / 2
    xyzText(2) = (xyz0(2) + xyz1(2)) / 2
    
    ' 畫中間點
    Call fn_drawCircle(xyzText)
    ' 寫文字
    Call fn_drawText(xyzText, strText, strTextPos)
    
    fn_drawPloyline = xyz1
End Function


' /////////////////////////////////////
Function fn_drawValve(xyz0() As Double, iMul As Integer, strDirection As String, strText As String, strTextPos As String)
    fn_drawValve = 0
    
    Dim xyz1(0 To 2) As String
    
    Dim objPL(7) As Acad3DPolyline
    Dim xyz(5) As Double
    
    ' 構造閥門,向右畫
    xyz(0) = xyz0(0): xyz(1) = xyz0(1): xyz(2) = xyz0(2)
    xyz(3) = xyz0(0) + 60: xyz(4) = xyz0(1): xyz(5) = xyz0(2)
    Set objPL(0) = ThisDrawing.ModelSpace.Add3DPoly(xyz)
    xyz(0) = xyz(3): xyz(2) = xyz(5) + 20: xyz(5) = xyz(5) - 20
    Set objPL(1) = ThisDrawing.ModelSpace.Add3DPoly(xyz)
    xyz(0) = xyz(0) + 10: xyz(3) = xyz(3) + 10
    Set objPL(2) = ThisDrawing.ModelSpace.Add3DPoly(xyz)
    xyz(3) = xyz(3) + 40
    Set objPL(3) = ThisDrawing.ModelSpace.Add3DPoly(xyz)
    xyz(2) = xyz(2) - 40: xyz(5) = xyz(5) + 40
    Set objPL(4) = ThisDrawing.ModelSpace.Add3DPoly(xyz)
    xyz(0) = xyz(0) + 40
    Set objPL(5) = ThisDrawing.ModelSpace.Add3DPoly(xyz)
    xyz(0) = xyz(0) + 10: xyz(3) = xyz(3) + 10
    Set objPL(6) = ThisDrawing.ModelSpace.Add3DPoly(xyz)
    xyz(2) = xyz(2) + 20: xyz(3) = xyz(3) + 60: xyz(5) = xyz(5) - 20
    Set objPL(7) = ThisDrawing.ModelSpace.Add3DPoly(xyz)
    
    ' 轉向
    Dim rotatePt1(0 To 2) As Double
    Dim rotatePt2(0 To 2) As Double
    Dim rotateAngle
    Dim xyzText1(0 To 2) As Double
    Dim xyzText2(0 To 2) As Double
    Dim arrStr
    
    ' 旋轉軸第二個點
    rotatePt2(0) = xyz0(0)
    rotatePt2(1) = xyz0(1)
    rotatePt2(2) = xyz0(2)
    
    ' 兩個編號座標
    xyzText1(0) = xyz0(0)
    xyzText1(1) = xyz0(1)
    xyzText1(2) = xyz0(2)
    xyzText2(0) = xyz0(0)
    xyzText2(1) = xyz0(1)
    xyzText2(2) = xyz0(2)
    
    ' 閥門末尾座標
    xyz1(0) = xyz0(0)
    xyz1(1) = xyz0(1)
    xyz1(2) = xyz0(2)
    
    ' 座標轉換
    rotateAngle = 0
    If InStr(strDirection, "f") <> 0 Then
        rotateAngle = 90: rotatePt2(2) = xyz0(2) + 10
        xyzText1(1) = xyzText1(1) + 50: xyzText2(1) = xyzText2(1) + 130
        xyz1(1) = xyz1(1) + 180
    ElseIf InStr(strDirection, "b") <> 0 Then
        rotateAngle = -90: rotatePt2(2) = xyz0(2) + 10
        xyzText1(1) = xyzText1(1) - 50: xyzText2(1) = xyzText2(1) - 130
        xyz1(1) = xyz1(1) - 180
    ElseIf InStr(strDirection, "r") <> 0 Then
        ' 默認,不需要處理旋轉
        xyzText1(0) = xyzText1(0) + 50: xyzText2(0) = xyzText2(0) + 130
        xyz1(0) = xyz1(0) + 180
    ElseIf InStr(strDirection, "l") <> 0 Then
        rotateAngle = 180: rotatePt2(2) = xyz0(2) + 10
        xyzText1(0) = xyzText1(0) - 50: xyzText2(0) = xyzText2(0) - 130
        xyz1(0) = xyz1(0) - 180
    ElseIf InStr(strDirection, "u") <> 0 Then
        rotateAngle = 90: rotatePt2(1) = xyz0(1) - 10
        xyzText1(2) = xyzText1(2) + 50: xyzText2(2) = xyzText2(2) + 130
        xyz1(2) = xyz1(2) + 180
    ElseIf InStr(strDirection, "d") <> 0 Then
        rotateAngle = -90: rotatePt2(1) = xyz0(1) - 10
        xyzText1(2) = xyzText1(2) - 50: xyzText2(2) = xyzText2(2) - 130
        xyz1(2) = xyz1(2) - 180
    End If
    
    rotateAngle = rotateAngle * 3.141592 / 180#
    rotatePt1(0) = xyz0(0)
    rotatePt1(1) = xyz0(1)
    rotatePt1(2) = xyz0(2)
    
    ' 旋轉
    If rotateAngle <> 0 Then
        For i = 0 To UBound(objPL)
            objPL(i).Rotate3D rotatePt1, rotatePt2, rotateAngle
        Next
    End If
    
    ' 畫中間點
    Call fn_drawCircle(xyzText1)
    Call fn_drawCircle(xyzText2)
    ' 寫文字
    arrStr = Split(strText, ",")
    Call fn_drawText(xyzText1, Trim(arrStr(0)), strTextPos)
    Call fn_drawText(xyzText2, Trim(arrStr(1)), strTextPos)
    
    fn_drawValve = xyz1
End Function


' /////////////////////////////////////
Function fn_drawCircle(xyz1() As Double)
    fn_drawCircle = 0
    
    Dim r As Double
    Dim xyz(2) As Double
    Dim xyz0(2) As Double
    Dim outerLoop(0 To 0) As AcadEntity
    Dim hatchObj As AcadHatch
    
    r = 5   ' 圓半徑
    xyz(0) = xyz1(0): xyz(1) = xyz1(1): xyz(2) = xyz1(2)
    xyz0(0) = xyz1(0): xyz0(1) = xyz1(1): xyz0(2) = 0
    
    PatternName = "SOLID"
    PatternType = 0
    bAssociativity = True
    
    Set outerLoop(0) = ThisDrawing.ModelSpace.AddCircle(xyz, r)    ' 畫圓
    Set hatchObj = ThisDrawing.ModelSpace.AddHatch(PatternType, PatternName, bAssociativity)  ' 填充
    hatchObj.AppendOuterLoop (outerLoop)
    hatchObj.Move xyz0, xyz
    hatchObj.Evaluate
    
    fn_drawCircle = -1
End Function


' /////////////////////////////////////
Function fn_drawText(xyz0() As Double, strText As String, strTextPos As String)
    fn_drawText = 0
    
    Dim textObj As AcadText
    Dim xyz(2) As Double
    Dim xyz1(2) As Double
    Dim xyz2(2) As Double
    Dim iSize
    Dim iDiff
    iDiff = 10
    iSize = 10
    
    If strTextPos = "f" Or strTextPos = "r" Then iDiff = 10
    If strTextPos = "b" Or strTextPos = "l" Then iDiff = -10
    
    xyz(0) = xyz0(0): xyz(1) = xyz0(1): xyz(2) = xyz0(2)
    xyz1(0) = xyz0(0) + iDiff: xyz1(1) = xyz0(1) + 3: xyz1(2) = xyz0(2)
    xyz2(0) = xyz0(0) + 3: xyz2(1) = xyz0(1) + iDiff: xyz2(2) = xyz0(2)
    
    Set textObj = ThisDrawing.ModelSpace.AddText(strText, xyz, iSize)
    If strTextPos = "f" Or strTextPos = "l" Then
        textObj.Alignment = acAlignmentRight
        textObj.TextAlignmentPoint = xyz
    End If
    If strTextPos = "f" Or strTextPos = "b" Then
        DblAngle = ThisDrawing.Utility.AngleToReal(-90, acDegrees)
        textObj.Rotation = DblAngle
        textObj.Move xyz, xyz2
    ElseIf strTextPos = "l" Or strTextPos = "r" Then
        textObj.Move xyz, xyz1
    End If
    
    fn_drawText = -1
End Function





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章