Community
Civil 3D Customization
Welcome to Autodesk’s AutoCAD Civil 3D Forums. Share your knowledge, ask questions, and explore popular AutoCAD Civil 3D Customization topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Importing Points

14 REPLIES 14
SOLVED
Reply
Message 1 of 15
tyler_youngHUJ76
782 Views, 14 Replies

Importing Points

I have an autolisp routine made that runs the Import Points option automatically. All the user needs to do is select the file to import.

 

The routine works the first time, and the problem i'm trying to solve is the case of duplicate numbers. The checkpointnumbers subroutine finds the largest point number in the drawing, and sets the offset to use with the new point file import. 

 
 

 

(defun c:-points ()
(setq c3d (vl-registry-read (strcat "HKEY_LOCAL_MACHINE\\" (if (vlax-user-product-key) (vlax-user-product-key) (vlax-product-key))) "Release"))
  (setq c3d2 (substr c3d 1 (vl-string-search "." c3d (+ (vl-string-search "." c3d) 1))))
  (setq c3ddoc (vla-get-activedocument (vla-getinterfaceobject (vlax-get-acad-object) (strcat "AeccXUiLand.AeccApplication." c3d2))))
  (setq pnts (vlax-get c3ddoc 'points))
  (setq pntopts (vla-getinterfaceobject (vlax-get-acad-object) (strcat "AeccXLand.AeccPointImportOptions." c3d2)))
  (if (setq cpss (ssget "X" '((0 . "AECC_COGO_POINT"))))
    (progn
      (checkpointnumbers)
      (setq inc (vlax-make-variant incoffset vlax-vbinteger))
      (vlax-put-property pntopts 'AddOffsetFrom inc)
      (vlax-put-property pntopts 'PointDuplicateResolution 1)
    )
  )
  (setq file (getfiled "Select an ASCII File to Import" (strcat (getvar "DWGPREFIX") "Field Data\\") "CSV;TXT" 4))
  (setq filename (nth (- (length (LM:str->lst file "\\")) 1) (LM:str->lst file "\\")))
  (setq layername (strcat "NoPlot-Points-" filename))
  (makelayer layername 3 0);this is subroutine that makes the layer
  (setvar "CLAYER" layername)
  (vlax-invoke pnts 'importpoints file "PNEZD (comma delimited)" pntopts)
  (vlax-release-object c3ddoc)
  (princ)
)
 
(defun checkpointnumbers (/ i numbers)
  (repeat (setq i (sslength cpss)) (setq numbers (append numbers (list (vlax-get-property (vlax-ename->vla-object (ssname cpss (setq i (1- i)))) 'number)))))
  (setq highestnumber (car (reverse numbers)))
  (cond
    ((< highestnumber 10000) (setq incoffset 10000))
    ((< highestnumber 20000) (setq incoffset 20000))
    ((< highestnumber 30000) (setq incoffset 30000))
    ((< highestnumber 40000) (setq incoffset 40000))
    ((< highestnumber 50000) (setq incoffset 50000))
    ((< highestnumber 60000) (setq incoffset 60000))
    ((< highestnumber 70000) (setq incoffset 70000))
    ((< highestnumber 80000) (setq incoffset 80000))
    ((< highestnumber 90000) (setq incoffset 90000))
    ((< highestnumber 100000) (setq incoffset 100000))
    ((< highestnumber 110000) (setq incoffset 110000))
    ((< highestnumber 120000) (setq incoffset 120000))
    ((< highestnumber 130000) (setq incoffset 130000))
    ((< highestnumber 140000) (setq incoffset 140000))
    ((< highestnumber 150000) (setq incoffset 150000))
    ((< highestnumber 160000) (setq incoffset 160000))
    ((< highestnumber 170000) (setq incoffset 170000))
    ((< highestnumber 180000) (setq incoffset 180000))
    ((< highestnumber 190000) (setq incoffset 190000))
    ((< highestnumber 200000) (setq incoffset 200000))
  )
);end defun

 

 
If I do (vlax-dump-object pntopts T) I get something like this:

 

Command: (vlax-dump-object pntopts T)
; IAeccPointImportOptions: IAeccPointImportOptions interface
; Property values:
; AddOffsetFrom = 10000
; AdjustElevation = 0
; ExpandCoordinateData = 0
; PointDuplicateResolution = 0
; PointGroup = ""
; SequenceFrom = 0
; TransformCoordinateT

 

 
So it is calculating the correct AddOffsetFrom as long as I don't have a point number greater than 9999, which is the present case. But it doesn't insert the next point file. The GUI pops up saying it detects duplicate point numbers. This is something I want to prevent, and having AddOffsetFrom filled in I thought this would work.
 
I've tried setting PointDuplicateResolution to 1 to see if that meant true, but it doesn't work then either.
 
Can anyone help me out with this?
14 REPLIES 14
Message 2 of 15
Jeff_M
in reply to: tyler_youngHUJ76

Unfortunately the PointImportOptions are ignored in lisp. Others have run into similar issues over the years when wanting to assign the PointGroup or AddOffsetFrom properties.

Jeff_M, also a frequent Swamper
EESignature
Message 3 of 15
Jeff_M
in reply to: tyler_youngHUJ76

@tyler_youngHUJ76 Your "-points" command can be accomplished using .NET.  Attached is a zip file containing a small file that can be NETLOADed into C3D 2022-2024. The downloaded zip will likely need to be Unblocked in the file's properties before you extract the dll to a folder of your choice.

 

The only code in it is below.

 

 

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.Civil.ApplicationServices;
using Autodesk.Civil.DatabaseServices;
using Autodesk.Civil.Settings;
using System.IO;
using System.Linq;

namespace CogoPointsImport
{
    public class PointsImporter
    {
        [CommandMethod("-Points")]
        public void pointsimport()
        {
            var ofd = new System.Windows.Forms.OpenFileDialog();
            ofd.Title = "Select an ASCII File to Import";
            ofd.Filter = "csv files (*.csv)|*.csv|txt files (*.txt)|*.txt";
            var path = (string)Application.GetSystemVariable("DWGPREFIX");
            path += "Field Data\\";
            ofd.InitialDirectory = path;
            if (ofd.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                return;
            var file = ofd.FileName;
            var filename = Path.GetFileName(file);
            var layername = "NoPlot-Points-" + filename;
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var civdoc = CivilApplication.ActiveDocument;
            CogoPointCollection pts = civdoc.CogoPoints;
            uint inc = 1;
            var ptSettings = civdoc.Settings.GetSettings<SettingsCmdCreatePoints>();
            var stgResolve = ptSettings.PointIdentity.ResolveDuplicatePointNumbersOption.Value;
            var stgHandle = ptSettings.PointIdentity.HandleSuppliedPointNumbersOption.Value;
            var stgKeys = ptSettings.PointsCreation.DisableDescriptionKeys.Value;
            var stgOffset = ptSettings.PointIdentity.PointNumberOffset.Value;
            ptSettings.PointIdentity.ResolveDuplicatePointNumbersOption.Value = Autodesk.Civil.PointNumbersExistType.Renumber;
            ptSettings.PointIdentity.HandleSuppliedPointNumbersOption.Value = Autodesk.Civil.PointNumbersSuppliedType.AddOffset;
            ptSettings.PointsCreation.DisableDescriptionKeys.Value = true;
            using (var tr = db.TransactionManager.StartTransaction())
            {
                setlayer(db, layername);
                ptSettings.Layer.Layer.Value = layername;
                if (pts.Count > 0)
                {
                    PointGroup ptgrp = (PointGroup)tr.GetObject( civdoc.PointGroups["_All Points"], OpenMode.ForRead);
                    var highestnumber = (uint)ptgrp.GetPointNumbers().OrderBy(x => x).Last();
                    inc = checkpointnumbers(highestnumber);
                    ptSettings.PointIdentity.PointNumberOffset.Value = inc;
                }
                var pffs = PointFileFormatCollection.GetPointFileFormats(db);
                PointFileFormat pff = pffs["PNEZD (comma delimited)"];
                var newPts = CogoPointCollection.ImportPoints(file, pff );
                tr.Commit();
            }
            ptSettings.PointIdentity.ResolveDuplicatePointNumbersOption.Value = stgResolve;
            ptSettings.PointIdentity.HandleSuppliedPointNumbersOption.Value = stgHandle;
            ptSettings.PointsCreation.DisableDescriptionKeys.Value = stgKeys;
            ptSettings.PointIdentity.PointNumberOffset.Value = stgOffset;
        }

        private void setlayer(Database db, string layername)
        {
            var lt = (LayerTable)db.LayerTableId.GetObject(OpenMode.ForRead);
            if (lt.Has(layername))
                return;
            var newlyr = new LayerTableRecord();
            newlyr.Name = layername;
            newlyr.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex(Autodesk.AutoCAD.Colors.ColorMethod.ByColor, 3);
            newlyr.IsPlottable = false;
            lt.UpgradeOpen();
            lt.Add(newlyr);
            db.TransactionManager.TopTransaction.AddNewlyCreatedDBObject(newlyr, true);
            lt.DowngradeOpen();
        }

        private uint checkpointnumbers(uint highestnumber)
        {
            uint retval = 10000;
            while (highestnumber > retval)
                retval += 10000;
            return retval;
        }
    }
}

 

 

  

Jeff_M, also a frequent Swamper
EESignature
Message 4 of 15
tyler_youngHUJ76
in reply to: Jeff_M

Thanks for the information on why the AutoLISP won't work. And thanks again for the .NET solution. I had tried to reply after your first message but the site was down. I worked on a new version and go figure this is should have been my first thought, as it works as I had hoped. .NET is good that it can access more than AutoLISP, but there is so much more code that needs to be done.

(defun c:-points ()
  (if (setq cpss (ssget "X" '((0 . "AECC_COGO_POINT")))) (checkpointnumbers))
  (setq openfile (open (setq file (getfiled "Select an ASCII File to Import" (strcat (getvar "DWGPREFIX") "Field Data\\") "CSV;TXT" 4)) "r"))
  (setq filename (nth (- (length (LM:str->lst file "\\")) 1) (LM:str->lst file "\\")))
  (setq layername (strcat "NoPlot-Points-" filename))
  (makelayer layername 3 0)
  (setvar "CLAYER" layername)
  (while (setq line (read-line openfile))
    (setq values (LM:str->lst line ","))
    (if incoffset (setq n (+ (atoi (nth 0 values)) incoffset)) (setq n (atoi (nth 0 values))))
    (setq y (nth 1 values))
    (setq x (nth 2 values))
    (setq z (nth 3 values))
    (setq d (nth 4 values))
    (setq p (strcat x "," y))
    (command "_AECCCREATEPOINTMANUAL" p "")
    (setq obj (vlax-ename->vla-object (entlast)))
    (vlax-put-property obj 'number n)
    (vlax-put-property obj 'rawdescription d)
    (vlax-put-property obj 'elevation z)
    (vlax-release-object obj)
  );end while
  (close openfile)
  (princ)
);end defun

 

Message 5 of 15

@Jeff_M  I really like the .NET solution. It's really fast and automatic. I can't seem to add one thing to the code you had provided. The layer the points are supposed to be on is not to be plotted. I'd like to have added that myself (and learn a little C# along the way) but I can't even build the .dll. I'm not configured to do so and I have a powershell exception on my computer that I can't install the .NET SDK in VSCODE that I use for my autolisp development. I added the C# dev kit and it had that error.

Would you be able to help me out one more time?

Message 6 of 15
Jeff_M
in reply to: tyler_youngHUJ76

@tyler_youngHUJ76 sure thing. I didn't know what, exactly, your makelayer function does, although I should have guessed that no plot part based on the name. Updated zip file attached and will update the source code once this is posted.

 

As for making edits yourself, you would need to have Visual Studio (or some other IDE, compatible with .NET/c#). If you decide to install one (Visual Studio 2022, Community Edition is free), I'd be happy to provide you with the project files.

 

**Edit: updated zip file with new file, 3/4/24

Jeff_M, also a frequent Swamper
EESignature
Message 7 of 15

@Jeff_M Thanks again, this one works as intended. As I had said before I use Visual Studio Code, which I know is different than Visual Stuido 2022. I figured out how to get the .NET SDK added in, and I also have the C# Dev Kit installed. I was able to create a project for the original version, but I know I need to configure things to get it to work right. I was reading many posts about it but haven't got it running yet. 

Message 8 of 15

@Jeff_M I tried this program on a new drawing, with no points in it. It didn't work. I got the following error.

 

Application does not support just-in-time (JIT)
debugging. See the end of this message for details.

************** Exception Text **************
System.ArgumentException: Error: integer attribute value '0' for attribute 'Point Number Offset' must be greater than 0 and less than or equal to 4294967295
at Autodesk.Civil.AttributeHelper.putAttributeGeneric<int>(UInt32 attributeId, IAeccAttributeBin* pAttrBin, Int32 newValue, AeccUserParam* userParam)
at Autodesk.Civil.Property<unsigned int\,int\,Autodesk::Civil::CastOp<unsigned int\,int> >.set_Value(UInt32 newValue)
at CogoPointsImport.PointsImporter.pointsimport()

 

**Edited by EE to remove unnecessary crash data.

Message 9 of 15

@Jeff_M it doesn't look like my last message worked. This program doesn't work if there are no existing points in the drawing ie: first run. So to me it looks like the if statement for the pts.Count needs another case for no points.

 

Message 10 of 15
Jeff_M
in reply to: tyler_youngHUJ76

@tyler_youngHUJ76 I edited the message with all the crash info.

 

The issue is that C3D doesn't like like the PointNumberOffset to be set to 0. I moved the set statement into the the section if the dwg contains points and all is well. I will replace the last message with the zip file with the corrected one and update the posted code as well.

Jeff_M, also a frequent Swamper
EESignature
Message 11 of 15

@Jeff_M this is a great project. Thanks again. I was able to get the rest of the files created to build the .dll again from the code you posted. However I'm curious as I ran a test on the version I made and it doesn't work. I wonder what is the framework you targeted? I can't think of anything else that might have ruined my build.

Message 12 of 15
Jeff_M
in reply to: tyler_youngHUJ76

Which release of Civil 3D are you using? I used .NET Framework 4.7.2 which allows it to work with Civil 3D 2022-2024
Jeff_M, also a frequent Swamper
EESignature
Message 13 of 15

@Jeff_M Currently I'm using 2023, but with Civil3D 2025 coming out in a few weeks I'll be testing that one out. I also have 2024 installed but don't currently use that. The info I was finding online was to use NET6.0. I'm just trying to see if I can work with C#. And given I know this is a working program I'm trying to rebuild it just to get that method down pat. 

 

Message 14 of 15
Jeff_M
in reply to: tyler_youngHUJ76

All releases of AutoCAD prior to the next release require a .NET Framework 4.X.X  2023 & 2024 can both use 4.8 

AutoCAD 2025 will be using .NET 8.0

Do you have all the required references added to the project? And set to not copy to build folder?

2024-03-05_17-00-47.png

Jeff_M, also a frequent Swamper
EESignature
Message 15 of 15
tyler_youngHUJ76
in reply to: Jeff_M

Yes, I had the correct AutoCAD .dlls added as references but I was targeting NET8.0. I've since downloaded 4.7.2 But Visual Studio Code doesn't like anything older than NET6.0 so I'll have to get Visual Studio 2022. 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Rail Community


 

Autodesk Design & Make Report