Thursday, February 10, 2005
Inserting Point Data into AutoCAD
Platform: AutoCAD 2004
Download: InsertPointData.zip
Many times throughout my career I've been required to insert point data into AutoCAD. I've dealt with raw DXF data; reverse engineered the extremely old DR2 file format from 2D Catia; teach point data from industrial robots and most recently 2D point data from an Excel chart. All of these require the same thing, take 2D or 3D points consisting of X, Y and possibly Z coordinates and place them in a CAD file. With vanilla AutoCAD, this is an extremely time consuming and error prone manual task; with a bit of programming it takes seconds.
I'll show two methods of bringing in 2D data, as points and as a lightweight polyline. The sample data I'll be using is tab separated, but you can easily change the code to work with any delimiter character. With both routines, I have hard coded the path to "C:\", either place the "pointdata.txt" file here or modify the path as you require.
Let's look at inserting the data as AutoCAD point objects. First, we load the file into a string variable. Using the Split command, the data is broken down into rows; then it's a matter of looping through the rows in the "ptArray" array and splitting each value into the "pt" array as Variant/Strings. AutoCAD will only accept point data as Variant/Doubles so we have to type cast the string data into the "point" array and then add the point to model space.
Public Sub Insert2DPointDataAsPoints()
On Error GoTo ErrorHandler
Dim oPoint As AcadPoint
Dim pt As Variant
Dim point(0 To 2) As Double
Dim ptArray As Variant
Dim fileNumber As Long
Dim strFile As String
Dim i As Long
' Open the text file and store it in strFile
fileNumber = FreeFile
Open "C:\pointdata.txt" For Binary Access Read As #fileNumber
strFile = String(LOF(fileNumber), " ")
If Not Len(strFile) = 0 Then Get #fileNumber, , strFile
Close #fileNumber
' Make sure we have some data to work with
' Also checks to see if user cancelled the dialog
If Len(Trim(strFile)) = 0 Then GoTo ErrorHandler
' Split the file into rows
ptArray = Split(strFile, vbCrLf)
For i = 0 To UBound(ptArray)
' Set the point
pt = Split(ptArray(i), vbTab)
' Convert the string data to doubles
point(0) = CDbl(pt(0))
point(1) = CDbl(pt(1))
' Add the point to Modelspace
Set oPoint = ThisDrawing.ModelSpace.AddPoint(point)
Next i
' Clean up
Set oPoint = Nothing
If IsDimArray(pt) Then Erase pt
If IsDimArray(point) Then Erase point
If IsDimArray(ptArray) Then Erase ptArray
Exit Sub
ErrorHandler:
Set oPoint = Nothing
If IsDimArray(pt) Then Erase pt
If IsDimArray(point) Then Erase point
If IsDimArray(ptArray) Then Erase ptArray
End Sub
Adding a lightweight polyline isn't that different. Instead of breaking down the string data into doubles, we dimension one large array for all the 2D data "points" and use a counter "cnt" to fill in the values with our loop. Once all the data is loaded into the point array, the lightweight polyline is added to Modelspace.
Public Sub Insert2DPointDataAsLWPolyline()
On Error GoTo ErrorHandler
Dim oLWPline As AcadLWPolyline
Dim pt As Variant
Dim points() As Double
Dim ptArray As Variant
Dim fileNumber As Long
Dim strFile As String
Dim i As Long
Dim cnt As Long
' Open the text file and store it in strFile
fileNumber = FreeFile
Open "C:\pointdata.txt" For Binary Access Read As #fileNumber
strFile = String(LOF(fileNumber), " ")
If Not Len(strFile) = 0 Then Get #fileNumber, , strFile
Close #fileNumber
' Make sure we have some data to work with
' Also checks to see if user cancelled the dialog
If Len(Trim(strFile)) = 0 Then GoTo ErrorHandler
' Split the file into rows
ptArray = Split(strFile, vbCrLf)
' Resize the points array for the lightweight polyline
ReDim points((UBound(ptArray) * 2) + 1)
' Set the counter
cnt = 0
For i = 0 To UBound(ptArray)
' Set the point
pt = Split(ptArray(i), vbTab)
' Convert the string data to doubles
points(cnt) = CDbl(pt(0))
points(cnt + 1) = CDbl(pt(1))
cnt = cnt + 2
Next i
' Add the Light Weight Polyline to Modelspace
Set oLWPline = ThisDrawing.ModelSpace.AddLightWeightPolyline(points)
' Clean up
Set oLWPline = Nothing
If IsDimArray(pt) Then Erase pt
If IsDimArray(points) Then Erase points
If IsDimArray(ptArray) Then Erase ptArray
Exit Sub
ErrorHandler:
Set oLWPline = Nothing
If IsDimArray(pt) Then Erase pt
If IsDimArray(points) Then Erase points
If IsDimArray(ptArray) Then Erase ptArray
End Sub
Before I forget again, add the helper routine "IsDimArray" used to clean up the arrays that were used.
Public Function IsDimArray(arr As Variant) As Boolean
On Error GoTo ErrorHandler
Dim i As Long
i = UBound(arr)
If Not i = -1 Then IsDimArray = True
Exit Function
ErrorHandler:
IsDimArray = False
End Function
Changing these routines to insert 3D data is as simple as splitting the point data into 3 doubles (for the Z coordinate) or using a polyline instead of a lightweight polyline. If you have any trouble with your own data, let me know; I'd be happy to lend a hand. A few other things that should be included for a fully useful routine:
Download: InsertPointData.zip
Many times throughout my career I've been required to insert point data into AutoCAD. I've dealt with raw DXF data; reverse engineered the extremely old DR2 file format from 2D Catia; teach point data from industrial robots and most recently 2D point data from an Excel chart. All of these require the same thing, take 2D or 3D points consisting of X, Y and possibly Z coordinates and place them in a CAD file. With vanilla AutoCAD, this is an extremely time consuming and error prone manual task; with a bit of programming it takes seconds.
I'll show two methods of bringing in 2D data, as points and as a lightweight polyline. The sample data I'll be using is tab separated, but you can easily change the code to work with any delimiter character. With both routines, I have hard coded the path to "C:\", either place the "pointdata.txt" file here or modify the path as you require.
Let's look at inserting the data as AutoCAD point objects. First, we load the file into a string variable. Using the Split command, the data is broken down into rows; then it's a matter of looping through the rows in the "ptArray" array and splitting each value into the "pt" array as Variant/Strings. AutoCAD will only accept point data as Variant/Doubles so we have to type cast the string data into the "point" array and then add the point to model space.
Public Sub Insert2DPointDataAsPoints()
On Error GoTo ErrorHandler
Dim oPoint As AcadPoint
Dim pt As Variant
Dim point(0 To 2) As Double
Dim ptArray As Variant
Dim fileNumber As Long
Dim strFile As String
Dim i As Long
' Open the text file and store it in strFile
fileNumber = FreeFile
Open "C:\pointdata.txt" For Binary Access Read As #fileNumber
strFile = String(LOF(fileNumber), " ")
If Not Len(strFile) = 0 Then Get #fileNumber, , strFile
Close #fileNumber
' Make sure we have some data to work with
' Also checks to see if user cancelled the dialog
If Len(Trim(strFile)) = 0 Then GoTo ErrorHandler
' Split the file into rows
ptArray = Split(strFile, vbCrLf)
For i = 0 To UBound(ptArray)
' Set the point
pt = Split(ptArray(i), vbTab)
' Convert the string data to doubles
point(0) = CDbl(pt(0))
point(1) = CDbl(pt(1))
' Add the point to Modelspace
Set oPoint = ThisDrawing.ModelSpace.AddPoint(point)
Next i
' Clean up
Set oPoint = Nothing
If IsDimArray(pt) Then Erase pt
If IsDimArray(point) Then Erase point
If IsDimArray(ptArray) Then Erase ptArray
Exit Sub
ErrorHandler:
Set oPoint = Nothing
If IsDimArray(pt) Then Erase pt
If IsDimArray(point) Then Erase point
If IsDimArray(ptArray) Then Erase ptArray
End Sub
Adding a lightweight polyline isn't that different. Instead of breaking down the string data into doubles, we dimension one large array for all the 2D data "points" and use a counter "cnt" to fill in the values with our loop. Once all the data is loaded into the point array, the lightweight polyline is added to Modelspace.
Public Sub Insert2DPointDataAsLWPolyline()
On Error GoTo ErrorHandler
Dim oLWPline As AcadLWPolyline
Dim pt As Variant
Dim points() As Double
Dim ptArray As Variant
Dim fileNumber As Long
Dim strFile As String
Dim i As Long
Dim cnt As Long
' Open the text file and store it in strFile
fileNumber = FreeFile
Open "C:\pointdata.txt" For Binary Access Read As #fileNumber
strFile = String(LOF(fileNumber), " ")
If Not Len(strFile) = 0 Then Get #fileNumber, , strFile
Close #fileNumber
' Make sure we have some data to work with
' Also checks to see if user cancelled the dialog
If Len(Trim(strFile)) = 0 Then GoTo ErrorHandler
' Split the file into rows
ptArray = Split(strFile, vbCrLf)
' Resize the points array for the lightweight polyline
ReDim points((UBound(ptArray) * 2) + 1)
' Set the counter
cnt = 0
For i = 0 To UBound(ptArray)
' Set the point
pt = Split(ptArray(i), vbTab)
' Convert the string data to doubles
points(cnt) = CDbl(pt(0))
points(cnt + 1) = CDbl(pt(1))
cnt = cnt + 2
Next i
' Add the Light Weight Polyline to Modelspace
Set oLWPline = ThisDrawing.ModelSpace.AddLightWeightPolyline(points)
' Clean up
Set oLWPline = Nothing
If IsDimArray(pt) Then Erase pt
If IsDimArray(points) Then Erase points
If IsDimArray(ptArray) Then Erase ptArray
Exit Sub
ErrorHandler:
Set oLWPline = Nothing
If IsDimArray(pt) Then Erase pt
If IsDimArray(points) Then Erase points
If IsDimArray(ptArray) Then Erase ptArray
End Sub
Before I forget again, add the helper routine "IsDimArray" used to clean up the arrays that were used.
Public Function IsDimArray(arr As Variant) As Boolean
On Error GoTo ErrorHandler
Dim i As Long
i = UBound(arr)
If Not i = -1 Then IsDimArray = True
Exit Function
ErrorHandler:
IsDimArray = False
End Function
Changing these routines to insert 3D data is as simple as splitting the point data into 3 doubles (for the Z coordinate) or using a polyline instead of a lightweight polyline. If you have any trouble with your own data, let me know; I'd be happy to lend a hand. A few other things that should be included for a fully useful routine:
- Watch for blank lines in the point data
- Check all the data to be sure it is numeric before adding the point
- Add code to make sure the point data file exists before trying to open it
Comments:
<< Home
Hi,
I'm developing a program that will frame a house based on its walls. I'm getting a model from Archicad, which contains each wall as blockreference.
I made an array of entities (block references) and now I want to explode them to get their coordinates.
Rigth now I have my array of block references but I'm trying to make one for the exploded objects (3dfaces) but it seems that it doesn't work. Can sombody give me an example of the code I should use?
Thanks
JUAN D MANRIQUE
Post a Comment
I'm developing a program that will frame a house based on its walls. I'm getting a model from Archicad, which contains each wall as blockreference.
I made an array of entities (block references) and now I want to explode them to get their coordinates.
Rigth now I have my array of block references but I'm trying to make one for the exploded objects (3dfaces) but it seems that it doesn't work. Can sombody give me an example of the code I should use?
Thanks
JUAN D MANRIQUE
<< Home
