RMS Posted June 26, 2010 Share Posted June 26, 2010 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 Quote Link to comment Share on other sites More sharing options...
Kerry Brown Posted June 26, 2010 Share Posted June 26, 2010 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. Quote Link to comment Share on other sites More sharing options...
SEANT Posted June 27, 2010 Share Posted June 27, 2010 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. Quote Link to comment Share on other sites More sharing options...
RMS Posted July 2, 2010 Author Share Posted July 2, 2010 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! Quote Link to comment Share on other sites More sharing options...
SEANT Posted July 2, 2010 Share Posted July 2, 2010 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! 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. Quote Link to comment Share on other sites More sharing options...
RMS Posted July 4, 2010 Author Share Posted July 4, 2010 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. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.