DXF.bas
上传用户:shushan03
上传日期:2019-11-23
资源大小:44k
文件大小:24k
源码类别:

CAD

开发平台:

Visual Basic

  1. Attribute VB_Name = "DXF"
  2. Option Explicit
  3. Const pi = 3.14159265358979
  4. Type RECT
  5.     X1 As Single
  6.     Y1 As Single
  7.     X2 As Single
  8.     Y2 As Single
  9. End Type
  10. Private Type LOGFONT
  11.   lfHeight As Long
  12.   lfWidth As Long
  13.   lfEscapement As Long
  14.   lfOrientation As Long
  15.   lfWeight As Long
  16.   lfItalic As Byte
  17.   lfUnderline As Byte
  18.   lfStrikeOut As Byte
  19.   lfCharSet As Byte
  20.   lfOutPrecision As Byte
  21.   lfClipPrecision As Byte
  22.   lfQuality As Byte
  23.   lfPitchAndFamily As Byte
  24. ' lfFaceName(LF_FACESIZE)
  25.   lfFacename As String * 33
  26. End Type
  27. Type DataSet
  28.     Key As Integer
  29.     Value As Variant
  30. End Type
  31. Type Geometry
  32.     Type As String
  33.     Data() As DataSet
  34. End Type
  35. Type Block
  36.     Name As String
  37.     Entities() As Geometry
  38. End Type
  39. Type DXFData
  40.     Blocks() As Block
  41.     Entities() As Geometry
  42. End Type
  43. Dim Section() As String
  44. Private Declare Function CreateFontIndirect Lib "gdi32" Alias "CreateFontIndirectA" (lpLogFont As LOGFONT) As Long
  45. Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
  46. Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
  47. Sub ClearKeys(ByRef Geo As Geometry)
  48. Dim i As Integer
  49. For i = 0 To UBound(Geo.Data)
  50.     Geo.Data(i).Key = i
  51. Next i
  52. End Sub
  53. Function dAngle(Angle As Single) As Single
  54. If Angle > 360 Then
  55.     dAngle = Angle - 360
  56. ElseIf Angle < 0 Then
  57.     dAngle = Angle + 360
  58. Else
  59.     dAngle = Angle
  60. End If
  61. End Function
  62. Function FindStart(sArray() As String, Start As Long)
  63. Dim i As Long
  64. For i = Start To UBound(sArray)
  65.     If sArray(i) = "10" And sArray(i + 2) = "20" Then
  66.         FindStart = i
  67.         Exit Function
  68.     End If
  69. Next i
  70. FindStart = -1
  71. End Function
  72. Sub PrepareEntity(ByRef Geo As Geometry)
  73. 'This may take a little more time during the "load"
  74. 'and it may take a little more memory, but in the end
  75. 'it will draw much faster
  76. Dim i As Integer
  77. Select Case Geo.Type
  78.     Case "LINE"
  79.         If UBound(Geo.Data) < 3 Then ReDim Preserve Geo.Data(3) As DataSet
  80.         Geo.Data(0).Value = kVal(Geo.Data(), 10)
  81.         Geo.Data(1).Value = kVal(Geo.Data(), 20)
  82.         Geo.Data(2).Value = kVal(Geo.Data(), 11)
  83.         Geo.Data(3).Value = kVal(Geo.Data(), 21)
  84.         ReDim Preserve Geo.Data(3) As DataSet
  85.     Case "ARC"
  86.         If UBound(Geo.Data) < 4 Then ReDim Preserve Geo.Data(4) As DataSet
  87.         Geo.Data(0).Value = kVal(Geo.Data(), 10)
  88.         Geo.Data(1).Value = kVal(Geo.Data(), 20)
  89.         Geo.Data(2).Value = kVal(Geo.Data(), 40)
  90.         Geo.Data(3).Value = kVal(Geo.Data(), 50)
  91.         Geo.Data(4).Value = kVal(Geo.Data(), 51)
  92.         ReDim Preserve Geo.Data(4) As DataSet
  93.     Case "CIRCLE"
  94.         If UBound(Geo.Data) < 2 Then ReDim Preserve Geo.Data(2) As DataSet
  95.         Geo.Data(0).Value = kVal(Geo.Data(), 10)
  96.         Geo.Data(1).Value = kVal(Geo.Data(), 20)
  97.         Geo.Data(2).Value = kVal(Geo.Data(), 40)
  98.         ReDim Preserve Geo.Data(2) As DataSet
  99.     Case "ELLIPSE"
  100.         If UBound(Geo.Data) < 6 Then ReDim Preserve Geo.Data(6) As DataSet
  101.         Geo.Data(0).Value = kVal(Geo.Data(), 10)
  102.         Geo.Data(1).Value = kVal(Geo.Data(), 20)
  103.         Geo.Data(2).Value = kVal(Geo.Data(), 11)
  104.         Geo.Data(3).Value = kVal(Geo.Data(), 21)
  105.         Geo.Data(4).Value = kVal(Geo.Data(), 40)
  106.         Geo.Data(5).Value = kVal(Geo.Data(), 41)
  107.         Geo.Data(6).Value = kVal(Geo.Data(), 42)
  108.         ReDim Preserve Geo.Data(6) As DataSet
  109.     Case "VERTEX"
  110.         If UBound(Geo.Data) < 1 Then ReDim Preserve Geo.Data(1) As DataSet
  111.         Geo.Data(0).Value = kVal(Geo.Data(), 10)
  112.         Geo.Data(1).Value = kVal(Geo.Data(), 20)
  113.         ReDim Preserve Geo.Data(1) As DataSet
  114.     Case "TEXT"
  115.         If UBound(Geo.Data) < 4 Then ReDim Preserve Geo.Data(4) As DataSet
  116.         Geo.Data(0).Value = kVal(Geo.Data(), 10)
  117.         Geo.Data(1).Value = kVal(Geo.Data(), 20)
  118.         Geo.Data(2).Value = kVal(Geo.Data(), 40)
  119.         Geo.Data(3).Value = kVal(Geo.Data(), 50)
  120.         Geo.Data(4).Value = kVal(Geo.Data(), 1)
  121.         ReDim Preserve Geo.Data(4) As DataSet
  122.     Case "INSERT"
  123.         If UBound(Geo.Data) < 5 Then ReDim Preserve Geo.Data(5) As DataSet
  124.         Geo.Data(0).Value = kVal(Geo.Data(), 2)
  125.         Geo.Data(1).Value = kVal(Geo.Data(), 10)
  126.         Geo.Data(2).Value = kVal(Geo.Data(), 20)
  127.         Geo.Data(3).Value = kVal(Geo.Data(), 41)
  128.         Geo.Data(4).Value = kVal(Geo.Data(), 42)
  129.         Geo.Data(5).Value = kVal(Geo.Data(), 50)
  130.         ReDim Preserve Geo.Data(5) As DataSet
  131.     Case "DIMENSION"
  132.         If UBound(Geo.Data) < 10 Then ReDim Preserve Geo.Data(10) As DataSet
  133.         Geo.Data(0).Value = kVal(Geo.Data(), 2)
  134.         Geo.Data(1).Value = kVal(Geo.Data(), 10)
  135.         Geo.Data(2).Value = kVal(Geo.Data(), 20)
  136.         Geo.Data(3).Value = kVal(Geo.Data(), 11)
  137.         Geo.Data(4).Value = kVal(Geo.Data(), 21)
  138.         Geo.Data(5).Value = kVal(Geo.Data(), 12)
  139.         Geo.Data(6).Value = kVal(Geo.Data(), 22)
  140.         Geo.Data(7).Value = kVal(Geo.Data(), 13)
  141.         Geo.Data(8).Value = kVal(Geo.Data(), 23)
  142.         Geo.Data(9).Value = kVal(Geo.Data(), 14)
  143.         Geo.Data(10).Value = kVal(Geo.Data(), 24)
  144.         ReDim Preserve Geo.Data(10) As DataSet
  145. End Select
  146. ClearKeys Geo
  147. End Sub
  148. Function PtAng(X1 As Single, Y1 As Single) As Single
  149. If X1 = 0 Then
  150.     If Y1 >= 0 Then
  151.         PtAng = 90
  152.     Else
  153.         PtAng = 270
  154.     End If
  155.     PtAng = PtAng * pi / 180
  156.     Exit Function
  157. ElseIf Y1 = 0 Then
  158.     If X1 >= 0 Then
  159.         PtAng = 0
  160.     Else
  161.         PtAng = 180
  162.     End If
  163.     PtAng = PtAng * pi / 180
  164.     Exit Function
  165. Else
  166.     PtAng = Atn(Y1 / X1)
  167.     PtAng = PtAng * 180 / pi
  168.     If PtAng < 0 Then PtAng = PtAng + 360
  169.     If PtAng > 360 Then PtAng = PtAng - 360
  170.     '----------Test for direction-(quadrant check)-------
  171.     If X1 < 0 Then PtAng = PtAng + 180
  172.     If Y1 < 0 And PtAng < 90 Then PtAng = PtAng + 180
  173.     'If X1 < 0 And PtAng <> 180 Then PtAng = PtAng + 180
  174.     'If Y1 < 0 And PtAng = 90 Then PtAng = PtAng + 180
  175.     
  176.     'One final check
  177.     If PtAng < 0 Then PtAng = PtAng + 360
  178.     If PtAng > 360 Then PtAng = PtAng - 360
  179.     PtAng = PtAng * pi / 180
  180. End If
  181. End Function
  182. Function cHyp(X1 As Single, Y1 As Single) As Single
  183. cHyp = Sqr((X1 * X1) + (Y1 * Y1))
  184. End Function
  185. Sub DrawDXF(Canvas As PictureBox, DXF As DXFData)
  186. On Error GoTo exitMe
  187. Canvas.Cls
  188. Canvas.Picture = LoadPicture()
  189. Dim i As Integer
  190. For i = 0 To UBound(DXF.Entities)
  191.     DrawDXFGeometry Canvas, DXF, DXF.Entities(), i, 0, 0, 1, 1, 0
  192. Next i
  193. Canvas.Picture = Canvas.Image
  194. exitMe:
  195. End Sub
  196. Sub DrawBlock(Canvas As PictureBox, DXF As DXFData, BlockNum As Integer)
  197. On Error GoTo exitMe
  198. Canvas.Cls
  199. Canvas.Picture = LoadPicture()
  200. Dim i As Integer
  201. For i = 0 To UBound(DXF.Blocks(BlockNum).Entities)
  202.     DrawDXFGeometry Canvas, DXF, DXF.Blocks(BlockNum).Entities(), i, 0, 0, 1, 1, 0
  203. Next i
  204. Canvas.Picture = Canvas.Image
  205. exitMe:
  206. End Sub
  207. Sub DrawDXFBlock(Canvas As PictureBox, DXF As DXFData, Name As String, cX As Single, cY As Single, ScaleX As Single, ScaleY As Single, Angle As Single)
  208. Dim i As Integer
  209. Dim bNum As Integer
  210. bNum = GetBlock(DXF, Name)
  211. For i = 0 To UBound(DXF.Blocks(bNum).Entities)
  212.     DrawDXFGeometry Canvas, DXF, DXF.Blocks(bNum).Entities(), i, cX, cY, ScaleX, ScaleY, Angle
  213. Next i
  214. End Sub
  215. Sub DrawDXFDImension(Canvas As PictureBox, DXF As DXFData, Name As String)
  216. Dim i As Integer
  217. Dim bNum As Integer
  218. bNum = GetBlock(DXF, Name)
  219. For i = 0 To UBound(DXF.Blocks(bNum).Entities)
  220.     DrawDXFGeometry Canvas, DXF, DXF.Blocks(bNum).Entities(), i, 0, 0, 1, 1, 0
  221. Next i
  222. End Sub
  223. Sub DrawDXFLine(Canvas As PictureBox, X1 As Single, Y1 As Single, X2 As Single, Y2 As Single, Color As Long)
  224. Canvas.Line (X1, -Y1)-(X2, -Y2), Color
  225. End Sub
  226. Sub DrawDXFText(Canvas As PictureBox, X1 As Single, Y1 As Single, Angle As Single, Size As Single, Text As String, Color As Long)
  227. Dim F As LOGFONT
  228. Dim hPrevFont As Long
  229. Dim hFont As Long
  230. Dim FontName As String
  231. Dim XSIZE As Integer
  232. Dim YSIZE As Integer
  233. F.lfEscapement = 10 * Val(Angle) 'rotation angle, in tenths
  234. FontName = "Arial Black" + Chr$(0) 'null terminated
  235. F.lfFacename = FontName
  236. XSIZE = Canvas.ScaleX(Size, 0, 2)
  237. YSIZE = Canvas.ScaleY(Size, 0, 2)
  238. If XSIZE = 0 Then XSIZE = 1
  239. If YSIZE = 0 Then YSIZE = 1
  240. F.lfWidth = (XSIZE * -15) / Screen.TwipsPerPixelY
  241. F.lfHeight = (YSIZE * -20) / Screen.TwipsPerPixelY
  242. hFont = CreateFontIndirect(F)
  243. hPrevFont = SelectObject(Canvas.hdc, hFont)
  244. Canvas.ForeColor = Color
  245. Canvas.CurrentX = X1
  246. Canvas.CurrentY = -Y1 - Size
  247. Canvas.Print Text
  248. '  Clean up, restore original font
  249. hFont = SelectObject(Canvas.hdc, hPrevFont)
  250. DeleteObject hFont
  251. End Sub
  252. Sub DrawDXFArc(Canvas As PictureBox, X1 As Single, Y1 As Single, rad As Single, Angle1 As Single, Angle2 As Single, Color As Long)
  253. Angle1 = dAngle(Angle1)
  254. Angle2 = dAngle(Angle2)
  255. Dim i As Single
  256. Dim interval As Single
  257. If Angle1 > Angle2 Then
  258.     If Angle1 <> 360 Then Canvas.Circle (X1, -Y1), rad, Color, Angle1 * pi / 180, 2 * pi
  259.     If Angle2 <> 0 Then Canvas.Circle (X1, -Y1), rad, Color, 0, Angle2 * pi / 180
  260. Else
  261.     'It's a good practice to ALWAYS split your arcs into sections
  262.     'this method may not draw it properly
  263.     'if the arc ever ends up being close to a circle (CLOSED)
  264.     interval = (Angle2 - Angle1) / pi
  265.     For i = Angle1 To Angle2 - interval Step interval
  266.         Canvas.Circle (X1, -Y1), rad, Color, i * pi / 180, (i + interval) * pi / 180
  267.     Next i
  268.     Canvas.Circle (X1, -Y1), rad, Color, i * pi / 180, (Angle2) * pi / 180
  269. End If
  270. End Sub
  271. Sub DrawDXFCircle(Canvas As PictureBox, X1 As Single, Y1 As Single, rad As Single, Color As Long)
  272. Canvas.Circle (X1, -Y1), rad, Color
  273. End Sub
  274. Sub DrawDXFPoint(Canvas As PictureBox, X1 As Single, Y1 As Single, Color As Long)
  275. Canvas.DrawWidth = 3
  276. Canvas.PSet (X1, -Y1), Color
  277. Canvas.DrawWidth = 1
  278. End Sub
  279. Sub DrawDXFEllipse(Canvas As PictureBox, cX As Single, cY As Single, mX As Single, mY As Single, Ratio As Single, Angle1 As Single, Angle2 As Single, NumPoints As Integer, Color)
  280. 'This was the HARDEST part of this project
  281. 'I don't know why . . it all seems simple now,
  282. 'but I had the hardest time figuring out how to rotate the ellipse
  283. 'none the less rotate an ellipse that isn't "closed"
  284. 'you CAN NOT simply use the windows API for drawing ellipses,
  285. 'because Windows does not allow rotation of the ellipse
  286. Dim A As Single, B As Single
  287. Dim RotAngle As Single
  288. Dim A1 As Single, A2 As Single
  289. Dim X1 As Single, Y1 As Single
  290. Dim X2 As Single, Y2 As Single
  291. Dim X3 As Single, Y3 As Single
  292. Dim Hyp As Single
  293. Dim j As Single
  294. Dim U As Single
  295. Dim Count As Integer
  296. A = Sqr((mX * mX) + (mY * mY))
  297. If mX < 0 Then A = -A
  298. B = Ratio * A
  299. If mX = 0 Then
  300.     RotAngle = pi / 2
  301. Else
  302.     RotAngle = Atn(mY / mX)
  303. End If
  304. For U = Angle1 To Angle2 + (pi / (NumPoints * 2)) Step pi / NumPoints
  305.     X1 = A * Cos(U)
  306.     Y1 = B * Sin(U)
  307.     Hyp = Sqr((X1 * X1) + (Y1 * Y1))
  308.     If X1 = 0 Then
  309.         j = pi / 2
  310.     Else
  311.         j = Atn(Y1 / X1)
  312.     End If
  313.     If X1 < 0 Then Hyp = -Hyp
  314.     If (j * 180 / pi) + (RotAngle * 180 / pi) > 360 Then j = j + (2 * pi)
  315.     X2 = (Hyp * Cos(RotAngle + j))
  316.     Y2 = (Hyp * Sin(RotAngle + j))
  317.     If Count > 0 Then Canvas.Line (cX + X3, -cY - Y3)-(cX + X2, -cY - Y2), Color
  318.     X3 = X2
  319.     Y3 = Y2
  320.     Count = Count + 1
  321. Next U
  322. End Sub
  323. Sub DrawDXFGeometry(Canvas As PictureBox, DXF As DXFData, Geo() As Geometry, Start As Integer, cX As Single, cY As Single, ScaleX As Single, ScaleY As Single, Angle As Single)
  324. 'When drawing geometry, and a 'modifier' is applied such as origin,scale or rotation
  325. 'you should follow the following order to draw geometry properly (when modified)
  326. '--------
  327. 'SCALE
  328. 'ROTATION
  329. 'ORIGIN
  330. '--------
  331. On Error Resume Next
  332. Dim Color As Long
  333. Dim i As Integer
  334. Dim X1 As Single
  335. Dim Y1 As Single
  336. Dim X2 As Single
  337. Dim Y2 As Single
  338. Dim X3 As Single
  339. Dim Y3 As Single
  340. Dim Angle1 As Single
  341. Dim Angle2 As Single
  342. Dim Angle3 As Single
  343. Dim Ratio As Single
  344. Dim rad As Single
  345. Dim PCount As Integer
  346. Dim Text As String
  347. Dim Size As Single
  348. Dim Name As String
  349. Dim EndPoly As Boolean
  350. Canvas.DrawWidth = 1
  351. Canvas.DrawStyle = vbSolid
  352. Color = vbBlack
  353. Select Case Geo(Start).Type
  354.     Case "LINE"
  355.         'Get the values
  356.         X1 = Geo(Start).Data(0).Value
  357.         Y1 = Geo(Start).Data(1).Value
  358.         X2 = Geo(Start).Data(2).Value
  359.         Y2 = Geo(Start).Data(3).Value
  360.         'Scale them relative to their origin
  361.         X1 = X1 * ScaleX
  362.         Y1 = Y1 * ScaleY
  363.         X2 = X2 * ScaleX
  364.         Y2 = Y2 * ScaleY
  365.         'Rotate them relative to their origin
  366.         If Angle <> 0 Then
  367.             X3 = RotX(X1, Y1, Angle)
  368.             Y3 = RotY(X1, Y1, Angle)
  369.             X1 = X3
  370.             Y1 = Y3
  371.             X3 = RotX(X2, Y2, Angle)
  372.             Y3 = RotY(X2, Y2, Angle)
  373.             X2 = X3
  374.             Y2 = Y3
  375.         End If
  376.         'Move the origin
  377.         X1 = X1 + cX
  378.         Y1 = Y1 + cY
  379.         X2 = X2 + cX
  380.         Y2 = Y2 + cY
  381.         'Draw the line
  382.         DrawDXFLine Canvas, X1, Y1, X2, Y2, Color
  383.     Case "ARC"
  384.         'Circles and arc's AUTOMATICALLY become ELLIPSES when scaled
  385.         X1 = Geo(Start).Data(0).Value
  386.         Y1 = Geo(Start).Data(1).Value
  387.         rad = Geo(Start).Data(2).Value
  388.         Angle1 = Geo(Start).Data(3).Value
  389.         Angle2 = Geo(Start).Data(4).Value
  390.         X1 = X1 * ScaleX
  391.         Y1 = Y1 * ScaleY
  392.         'You can't "STRETCH' an arc . . . or any BLOCK for that matter
  393.         'If you stretch and ARC or a circle in the PV . . .it becomes an ellipse
  394.         If ScaleX <> 1 Then
  395.             rad = rad * ScaleX
  396.         ElseIf ScaleY <> 1 Then
  397.             rad = rad * ScaleY
  398.         End If
  399.         If Angle <> 0 Then
  400.             X3 = RotX(X1, Y1, Angle)
  401.             Y3 = RotY(X1, Y1, Angle)
  402.             X1 = X3
  403.             Y1 = Y3
  404.         End If
  405.         If ScaleX < 0 Or ScaleY < 0 Then
  406.             'the ARC is mirrored
  407.             Swap Angle1, Angle2
  408.             Angle1 = 180 - Angle1
  409.             Angle2 = 180 - Angle2
  410.         End If
  411.         Angle1 = Angle1 + (Angle * 180 / pi)
  412.         Angle2 = Angle2 + (Angle * 180 / pi)
  413.         X1 = X1 + cX
  414.         Y1 = Y1 + cY
  415.         DrawDXFArc Canvas, X1, Y1, Abs(rad), Angle1, Angle2, Color
  416.     Case "CIRCLE"
  417.         'Circles and arc's AUTOMATICALLY become ELLIPSES when scaled
  418.         X1 = Geo(Start).Data(0).Value
  419.         Y1 = Geo(Start).Data(1).Value
  420.         rad = Geo(Start).Data(2).Value
  421.         X1 = X1 * ScaleX
  422.         Y1 = Y1 * ScaleY
  423.         If ScaleX <> 1 Then
  424.             rad = rad * ScaleX
  425.         ElseIf ScaleY <> 1 Then
  426.             rad = rad * ScaleY
  427.         End If
  428.         If Angle <> 0 Then
  429.             X3 = RotX(X1, Y1, Angle)
  430.             Y3 = RotY(X1, Y1, Angle)
  431.             X1 = X3
  432.             Y1 = Y3
  433.         End If
  434.         X1 = X1 + cX
  435.         Y1 = Y1 + cY
  436.         DrawDXFCircle Canvas, X1, Y1, Abs(rad), Color
  437.     Case "ELLIPSE"
  438.         X1 = Geo(Start).Data(0).Value
  439.         Y1 = Geo(Start).Data(1).Value
  440.         X2 = Geo(Start).Data(2).Value
  441.         Y2 = Geo(Start).Data(3).Value
  442.         Ratio = Geo(Start).Data(4).Value
  443.         Angle1 = Geo(Start).Data(5).Value
  444.         Angle2 = Geo(Start).Data(6).Value
  445.         X1 = X1 * ScaleX
  446.         Y1 = Y1 * ScaleY
  447.         X2 = X2 * ScaleX
  448.         Y2 = Y2 * ScaleY
  449.         If Angle <> 0 Then
  450.             X3 = RotX(X1, Y1, Angle)
  451.             Y3 = RotY(X1, Y1, Angle)
  452.             X1 = X3
  453.             Y1 = Y3
  454.             X3 = RotX(X2, Y2, Angle)
  455.             Y3 = RotY(X2, Y2, Angle)
  456.             X2 = X3
  457.             Y2 = Y3
  458.         End If
  459.         If ScaleX < 0 Or ScaleY < 0 Then Ratio = -Ratio 'the ELLIPSE is mirrored
  460.         X1 = X1 + cX
  461.         Y1 = Y1 + cY
  462.         DrawDXFEllipse Canvas, X1, Y1, X2, Y2, Ratio, Angle1, Angle2, 32, Color
  463.     Case "POLYLINE"
  464.         'a POLYLINE is a list of "VERTEX" points that are strung together
  465.         PCount = 1
  466.         EndPoly = False
  467.         Do While Not EndPoly
  468.             X1 = Geo(Start + PCount).Data(0).Value
  469.             Y1 = Geo(Start + PCount).Data(1).Value
  470.             X2 = Geo(Start + PCount + 1).Data(0).Value
  471.             Y2 = Geo(Start + PCount + 1).Data(1).Value
  472.             'Scale them relative to their origin
  473.             X1 = X1 * ScaleX
  474.             X2 = X2 * ScaleX
  475.             Y1 = Y1 * ScaleY
  476.             Y2 = Y2 * ScaleY
  477.             'Rotate them relative to their origin
  478.             If Angle <> 0 Then
  479.                 X3 = RotX(X1, Y1, Angle)
  480.                 Y3 = RotY(X1, Y1, Angle)
  481.                 X1 = X3
  482.                 Y1 = Y3
  483.                 X3 = RotX(X2, Y2, Angle)
  484.                 Y3 = RotY(X2, Y2, Angle)
  485.                 X2 = X3
  486.                 Y2 = Y3
  487.             End If
  488.             'Move the origin
  489.             X1 = X1 + cX
  490.             Y1 = Y1 + cY
  491.             X2 = X2 + cX
  492.             Y2 = Y2 + cY
  493.             'Dray the line
  494.             DrawDXFLine Canvas, X1, Y1, X2, Y2, Color
  495.             PCount = PCount + 1
  496.             If Start + PCount + 1 > UBound(Geo) Then
  497.                 EndPoly = True
  498.             ElseIf Geo(Start + PCount + 1).Type <> "VERTEX" Then
  499.                 EndPoly = True
  500.             End If
  501.         Loop
  502.     Case "TEXT"
  503.         'there is no scaling for TEXT entities
  504.         X1 = Geo(Start).Data(0).Value
  505.         Y1 = Geo(Start).Data(1).Value
  506.         Size = Geo(Start).Data(2).Value
  507.         Angle1 = Geo(Start).Data(3).Value + Angle
  508.         Text = Geo(Start).Data(4).Value
  509.         'Move the origin
  510.         X1 = X1 + cX
  511.         Y1 = Y1 + cY
  512.         DrawDXFText Canvas, X1, Y1, Angle1, Size, Text, Color
  513.     Case "INSERT"
  514.         'Just a note: BLOCKS can not be "Stretched" but if they are mirrored . . that
  515.         'shows up in the "scale" dataset for BLOCKS
  516.         Name = Geo(Start).Data(0).Value
  517.         X1 = Geo(Start).Data(1).Value
  518.         Y1 = Geo(Start).Data(2).Value
  519.         X2 = Geo(Start).Data(3).Value
  520.         Y2 = Geo(Start).Data(4).Value
  521.         '"0" scale = scale of "1"
  522.         If X2 = 0 Then X2 = 1
  523.         If Y2 = 0 Then Y2 = 1
  524.         Angle1 = Geo(Start).Data(5).Value * pi / 180
  525.         DrawDXFBlock Canvas, DXF, Name, X1, Y1, X2, Y2, Angle1
  526.     Case "DIMENSION"
  527.         'Just a note: BLOCKS can not be "Stretched" but if they are mirrored . . that
  528.         'shows up in the "scale" dataset for BLOCKS
  529.         Name = Geo(Start).Data(0).Value
  530.         X1 = Geo(Start).Data(1).Value
  531.         Y1 = Geo(Start).Data(2).Value
  532.         DrawDXFDImension Canvas, DXF, Name
  533. End Select
  534. End Sub
  535. Sub FindCommand(FileNum As Integer, Command As String)
  536. Dim X As String
  537. Do While UCase(Trim(X)) <> UCase(Command)
  538.     Line Input #FileNum, X
  539. Loop
  540. End Sub
  541. Function GetBlock(DXF As DXFData, Name As String) As Integer
  542. Dim i As Integer
  543. For i = 0 To UBound(DXF.Blocks)
  544.     If DXF.Blocks(i).Name = Name Then
  545.         GetBlock = i
  546.         Exit Function
  547.     End If
  548. Next i
  549. End Function
  550. Function GetSection(FileNum As Integer, Start As String, Finish As String, EndString As String, sArray() As String) As Boolean
  551. ReDim sArray(0) As String
  552. Dim Temp As String
  553. Dim i As Long
  554. Do While Temp <> Start
  555.     Line Input #FileNum, Temp
  556.     Temp = UCase(Trim(Temp))
  557.     If Temp = EndString Then
  558.         GetSection = False
  559.         Exit Function
  560.     End If
  561. Loop
  562. Do While Temp <> Finish
  563.     Line Input #FileNum, Temp
  564.     Temp = UCase(Trim(Temp))
  565.     If Temp <> Finish Then
  566.         ReDim Preserve sArray(i) As String
  567.         sArray(i) = Temp
  568.         i = i + 1
  569.     End If
  570. Loop
  571. GetSection = True
  572. End Function
  573. Sub ImportDXF(FileDXF As String, ByRef DXF As DXFData)
  574. Dim FF As Integer
  575. Dim DXFLine As String
  576. Dim bCount As Integer
  577. Dim eCount As Integer
  578. Dim ENDSEC As Boolean
  579. ReDim DXF.Blocks(0) As Block
  580. ReDim DXF.Entities(0) As Geometry
  581. FF = FreeFile
  582. Open FileDXF For Input As #FF
  583. 'First we skip all the header stuff and get to the section called 'BLOCKS'
  584. FindCommand FF, "BLOCKS"
  585. '---------------------------
  586. 'BLOCKS are groups of geometry that
  587. 'are re-useable within the drawing
  588. 'they may appear several times within one drawing
  589. 'and if the block is modified it automatically
  590. 'modifies each time wherev it's used within the drawing
  591. Do While Not ENDSEC
  592.     'First we load in a SECTION into an array (BLOCK) to (ENDBLK)
  593.     'we do this until we come across the "ENDSEC" command
  594.     If GetSection(FF, "BLOCK", "ENDBLK", "ENDSEC", Section()) Then
  595.         'We have a "BLOCK" in the array
  596.         'So we have to advance our array of BLOCKS
  597.         ReDim Preserve DXF.Blocks(bCount) As Block
  598.         ReDim Preserve DXF.Blocks(bCount).Entities(eCount) As Geometry
  599.         If ParseBlock(Section(), DXF.Blocks(bCount)) Then
  600.             bCount = bCount + 1
  601.             eCount = 0
  602.         End If
  603.     Else
  604.         ENDSEC = True
  605.     End If
  606. Loop
  607. 'Now we go after the 'Primary View Entities
  608. ENDSEC = False
  609. eCount = 0
  610. GetSection FF, "ENTITIES", "ENDSEC", "ENDSEC", Section()
  611. 'This grabs ALL PV ENTITIES . . . kind of like one huge block
  612. Close #FF 'We can close the file because we're finished with it
  613. 'Next we fill the array with geometry data
  614. ParsePV Section(), DXF.Entities()
  615. End Sub
  616. Function IsCommand(InText As String)
  617. Select Case UCase(InText)
  618.     Case "LINE", "VERTEX", "POLYLINE", "CIRCLE", "ARC", "ELLIPSE", "TEXT", "INSERT", "DIMENSION"
  619.         'These are the basic ENTITY COMMANDS available in the DXF language
  620.         IsCommand = True
  621.     Case Else
  622.         IsCommand = False
  623. End Select
  624. End Function
  625. Function kVal(Data() As DataSet, Key As Integer) As Variant
  626. Dim i As Integer
  627. For i = 0 To UBound(Data)
  628.     If Data(i).Key = Key Then
  629.         kVal = Data(i).Value
  630.         Exit Function
  631.     End If
  632. Next i
  633. kVal = 0
  634. End Function
  635. Function ParseBlock(sArray() As String, ByRef tBlock As Block) As Boolean
  636. 'On Local Error GoTo exitMe:
  637. Dim i As Long
  638. Dim j As Long
  639. Dim k As Long
  640. Dim p As Long
  641. 'first we have to look for a section "6" to determine if this BLOCK section is "important"
  642. i = SearchSection(sArray(), i, "6")
  643. If i = -1 Then
  644.     ParseBlock = False
  645.     Exit Function
  646. End If
  647. i = SearchSection(sArray(), i, "2") + 1
  648. tBlock.Name = sArray(i)
  649. For j = i To UBound(sArray)
  650.     If IsCommand(sArray(j)) Then 'We Found an ENTITY COMMAND
  651.         ReDim Preserve tBlock.Entities(k) As Geometry
  652.         tBlock.Entities(k).Type = sArray(j)
  653.         'I am not sure if a BLOCK can use a block.
  654.         'Either way, this is designed to work even if you can
  655.         Select Case tBlock.Entities(k).Type
  656.             Case "INSERT", "DIMENSION"
  657.                 'KEY "2" on an INSERT provides the BLOCK name to be inserted
  658.                 j = SearchSection(sArray(), j, "2")
  659.             Case Else
  660.                 j = FindStart(sArray(), j)
  661.                 'j = SearchSection(sArray(), j, "10")
  662.         End Select
  663.         Do While sArray(j) <> "0"
  664.             ReDim Preserve tBlock.Entities(k).Data(p)
  665.             tBlock.Entities(k).Data(p).Key = sArray(j)
  666.             tBlock.Entities(k).Data(p).Value = sArray(j + 1)
  667.             p = p + 1
  668.             j = j + 2
  669.         Loop
  670.         PrepareEntity tBlock.Entities(k)
  671.         k = k + 1
  672.         p = 0
  673.     End If
  674. Next j
  675. ParseBlock = True
  676. Exit Function
  677. exitMe:
  678. MsgBox "ERROR  " & Err.Description
  679. End Function
  680. Function ParsePV(sArray() As String, ByRef tGeo() As Geometry) As Boolean
  681. Dim i As Long
  682. Dim j As Long
  683. Dim k As Long
  684. Dim p As Long
  685. For j = i To UBound(sArray)
  686.     If IsCommand(sArray(j)) Then 'we found an ENTITY COMMAND
  687.         ReDim Preserve tGeo(k) As Geometry
  688.         tGeo(k).Type = sArray(j)
  689.         Select Case tGeo(k).Type
  690.             Case "INSERT", "DIMENSION"
  691.                 'KEY "2" on an INSERT provides the BLOCK name to be inserted to the PV
  692.                 j = SearchSection(sArray(), j, "2")
  693.             Case Else
  694.                 j = FindStart(sArray(), j)
  695.                 'j = SearchSection(sArray(), j, "10")
  696.         End Select
  697.         Do While sArray(j) <> "0"
  698.             ReDim Preserve tGeo(k).Data(p)
  699.             tGeo(k).Data(p).Key = sArray(j)
  700.             tGeo(k).Data(p).Value = sArray(j + 1)
  701.             p = p + 1
  702.             j = j + 2
  703.         Loop
  704.         PrepareEntity tGeo(k)
  705.         k = k + 1
  706.         p = 0
  707.     End If
  708. Next j
  709. ParsePV = True
  710. End Function
  711. Function RotX(X1 As Single, Y1 As Single, Angle As Single) As Single
  712. RotX = cHyp(X1, Y1) * Cos(PtAng(X1, Y1) + Angle)
  713. End Function
  714. Function RotY(X1 As Single, Y1 As Single, Angle As Single) As Single
  715. RotY = cHyp(X1, Y1) * Sin(PtAng(X1, Y1) + Angle)
  716. End Function
  717. Function SearchSection(sArray() As String, Start As Long, Value As String) As Long
  718. Dim i As Long
  719. For i = Start To UBound(sArray)
  720.     If sArray(i) = Value Then
  721.         SearchSection = i
  722.         Exit Function
  723.     End If
  724. Next i
  725. SearchSection = -1
  726. End Function
  727. Sub Swap(ByRef A As Variant, ByRef B As Variant)
  728. Dim C As Variant
  729. C = A
  730. A = B
  731. B = C
  732. End Sub