Jump to content

VB.Net Code to Read a CSV Point File (Tutorial)


RMS

Recommended Posts

This code will read a CSV point file such as what Spatial Analyzer (SA Software) would output from a laser scan of some item, product, or an as built condition. This data can then be read into AutoCAD (in this case) to view and create something from the point data that was scanned. I have supplied a sample CSV text file that contains 49 points but I have used this code to read in over 20,000 points.

 

 

 


'    File Name: ReadPointsFromSA
'  Description: Read a CSV point file from SpatialAnalyzer (SA)
'           By: Robert Souza
' Contact info: dreamtoneamps[AT]gmail.com
'         Date: June 25, 2010


Option Strict On
Imports System.IO
Imports System.Windows

Imports Autodesk.AutoCAD.Colors
Imports Autodesk.AutoCAD.Windows
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.ApplicationServices


Public Class Class1

   Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
   Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
   Dim acCurDb As Database = acDoc.Database


   <CommandMethod("SApoints")> _
   Public Sub createLine()

       Dim CSV_FileName As String = Nothing

       ' navigate to the point text csv file using a file dialog
       Dim dlg As New System.Windows.Forms.OpenFileDialog()
       dlg.InitialDirectory = "C:\"
       dlg.Filter = "csv text files (*.txt)|*.txt|csv excel files (*.csv)|*.csv|All files (*.*)|*.*"

       If dlg.ShowDialog() = Windows.Forms.DialogResult.OK Then

           CSV_FileName = dlg.FileName().ToString
           ' call sub to create points from CSV file
           readCSVPoints(CSV_FileName)

       Else

           ' if canceled write to the command line and sub not called
           ed.WriteMessage(vbCr & " command canceled")

       End If


   End Sub


   Public Sub readCSVPoints(ByVal CSV_FileName As String)

       Dim myPath As String = CSV_FileName

       ' Start a transaction
       Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()

           ' Open the Block table for read
           Dim acBlkTbl As BlockTable
           acBlkTbl = CType(acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead), BlockTable)

           ' Open the Block table record Model space for write
           Dim acBlkTblRec As BlockTableRecord
           acBlkTblRec = CType(acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord)


           ' Read a line containing (point ID, x, y, z) points from a text file that contains coordinates

           Dim inputRecord As String = Nothing

           Dim myPoints(3) As String
           Dim x, y, z As Double
           ' point ID
           Dim pid As String

           Dim inReader As StreamReader = File.OpenText(myPath)

           ' Start reading text file one line at a time 
           inputRecord = inReader.ReadLine()

           While (inputRecord IsNot Nothing)

               If inputRecord.Contains(",") Then

                   myPoints = inputRecord.Split(CChar(",")) ' get code string

                   pid = (myPoints(0).Trim)
                   x = CDbl(myPoints(1).Trim)
                   y = CDbl(myPoints(2).Trim)
                   z = CDbl(myPoints(3).Trim)

                   ' Create a point at (x, y, z) in Model space
                   Dim acPoint As DBPoint = New DBPoint(New Point3d(x, y, z))
                   acPoint.SetDatabaseDefaults()

                   ' create point ID text with single line text i.e. (p1 text just above the point)
                   Dim acText As DBText = New DBText()
                   acText.SetDatabaseDefaults()
                   acText.Position = New Point3d((x - 0.25), (y + 0.075), z)
                   acText.Height = 0.125
                   acText.TextString = pid

                   ' call sub and place items on a layer of their own
                   CreateLayer(acPoint, acText)

                   ' Add the new object to the block table record and the transaction
                   acBlkTblRec.AppendEntity(acText)
                   acTrans.AddNewlyCreatedDBObject(acText, True)

                   ' Add the new object to the block table record and the transaction
                   acBlkTblRec.AppendEntity(acPoint)
                   acTrans.AddNewlyCreatedDBObject(acPoint, True)

               End If

               ' Read next line
               inputRecord = inReader.ReadLine()

           End While ' will end at EOF or keep looping

           ' Set the style for all point objects in the drawing
           acCurDb.Pdmode = 32    ' point style circle w/dot
           acCurDb.Pdsize = 0.125 ' value 1 or more is absolute size; 0 is 5%

           ' set iso mode
           ToIsoView()
           ' zoom all
           SendACommandToAutoCAD()
           ' now write to the command line
           ed.WriteMessage(vbCr & "all points are in")
           ' save the new object to the database
           acTrans.Commit()
           ' close reader to text file
           inReader.Close()

       End Using

   End Sub


   Public Sub CreateLayer(ByVal acPoint As DBPoint, ByVal acText As DBText)

       Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()

           ' Open the Layer table for read
           Dim acLyrTbl As LayerTable
           acLyrTbl = CType(acTrans.GetObject(acCurDb.LayerTableId, OpenMode.ForRead), LayerTable)

           Dim pLayerName As String = "110"
           Dim pidLayerName As String = "109"

           If acLyrTbl.Has(pLayerName) = False Then

               Dim acLyrTblRec As LayerTableRecord = New LayerTableRecord()

               ' Assign the layer the ACI color 1 and a name
               acLyrTblRec.Color = Color.FromColorIndex(ColorMethod.ByAci, 1)

               acLyrTblRec.Name = pLayerName

               ' Upgrade the Layer table for write
               acLyrTbl.UpgradeOpen()

               ' Append the new layer to the Layer table and the transaction
               acLyrTbl.Add(acLyrTblRec)
               acTrans.AddNewlyCreatedDBObject(acLyrTblRec, True)

           End If

           If acLyrTbl.Has(pidLayerName) = False Then

               Dim acLyrTblRec As LayerTableRecord = New LayerTableRecord()

               ' Assign the layer the ACI color 1 and a name
               acLyrTblRec.Color = Color.FromColorIndex(ColorMethod.ByAci, 5)
               acLyrTblRec.Name = pidLayerName

               ' Upgrade the Layer table for write
               acLyrTbl.UpgradeOpen()

               ' Append the new layer to the Layer table and the transaction
               acLyrTbl.Add(acLyrTblRec)
               acTrans.AddNewlyCreatedDBObject(acLyrTblRec, True)

           End If

           ' set each point to this layer
           acPoint.Layer = pLayerName

           ' set each point ID to this layer
           acText.Layer = pidLayerName

           ' Save the changes and dispose of the transaction
           acTrans.Commit()

       End Using

   End Sub


   ' zoom all
   Public Sub SendACommandToAutoCAD()
       ' limits of the drawing
       acDoc.SendStringToExecute("._zoom _all ", True, False, False)

   End Sub


   Public Sub ToIsoView()

       Dim vtr As ViewTableRecord = ed.GetCurrentView()
       Dim newVtr As ViewTableRecord = vtr
       newVtr.ViewDirection = New Vector3d(1, -1, 1)
       ed.SetCurrentView(newVtr)

   End Sub

End Class

points3D.txt

Link to comment
Share on other sites

Is there any way in this forum software to make the code panes large enough to read code properly.

 

On a 24" monitor that code pane takes up about a quarter of the screen ... what a waste !!

 

...

[add]

.. and added to that the the viewer needs to scroll vertical and horizontal just to get an idea of the intent.

Link to comment
Share on other sites

This code will read a CSV point file such as what Spatial Analyzer (SA Software) would output from a laser scan of some item, product, or an as built condition. This data can then be read into AutoCAD (in this case) to view and create something from the point data that was scanned. I have supplied a sample CSV text file that contains 49 points but I have used this code to read in over 20,000 points.

 

Nicely done. Inputting 20,000 points definitely requires automation. I do have to say that the sample point file you included was a rather boring shape, though.:)

Link to comment
Share on other sites

Nicely done. Inputting 20,000 points definitely requires automation. I do have to say that the sample point file you included was a rather boring shape, though.:)

 

Thank You!

 

I would love to share the ones that I work with at 10 - 20k points but.........we have rules at my work place I must obey! :o

Link to comment
Share on other sites

Thank You!

 

I would love to share the ones that I work with at 10 - 20k points but.........we have rules at my work place I must obey! :o

 

I understand.

 

 

Another peek at the code above has prompted a couple of suggestions:

 

If the layer assignment was not part of the CreateLayer sub then that sub could be called before the ‘While’ loop and avoid repeated StartTransactions and LayerTable Opens. The layer assignments could happen within the loop with the assurance that the layers already exist.

 

It does make sense that the user would place the Text/Points into Modelspace, but the program allows itself to be called while in Paperspace. Not necessarily a problem in that the entities are explicitly added to the proper BlockTableRecord, except that

newVtr.ViewDirection = New Vector3d(1, -1, 1)

is not allowed in Paperspace.

Link to comment
Share on other sites

I understand.

 

 

Another peak at the code above has prompted a couple of suggestions:

 

If the layer assignment was not part of the CreateLayer sub then that sub could be called before the ‘While’ loop and avoid repeated StartTransactions and LayerTable Opens. The layer assignments could happen within the loop with the assurance that the layers already exist.

 

It does make sense that the user would place the Text/Points into Modelspace, but the program allows itself to be called while in Paperspace. Not necessarily a problem in that the entities are explicitly added to the proper BlockTableRecord, except that

newVtr.ViewDirection = New Vector3d(1, -1, 1)

is not allowed in Paperspace.

 

Thanks for these suggestions, one thing I can comment on is the ToIsoView() Sub, and ZoomAll; I had a hard time finding an example that would work using AutoCAD 2008 and the AutoCAD developer's guide that I have seen seems to be for 2011.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...