C# How to create AutoCAD entities

I created a node for Dynamo in C# to extract data from Civil 3D objects. It is no problem to create Dynamo geometry. For testing purpose I created a list of Points which are visible in Dynamo and now I want to create DBPoints in AutoCAD from these collected points. This is part of the code:

 try
        {
            using (dynAppServ.DocumentContext ctx = new dynAppServ.DocumentContext(document.AcDocument))
            {
                using (acDbServ.Transaction tr = ctx.Transaction)
                {
                    acDbServ.BlockTableRecord btrCS = (acDbServ.BlockTableRecord)tr.GetObject(ctx.Database.CurrentSpaceId, acDbServ.OpenMode.ForWrite);

                    foreach (Point point in points)
                    {
                        acDbServ.DBPoint node = new acDbServ.DBPoint(new Point3d(point.X, point.Y, point.Z));
                        node.SetDatabaseDefaults();
                        node.Layer = "0";

                        btrCS.AppendEntity(node);
                        tr.AddNewlyCreatedDBObject(node, true);

                    }
                    tr.Commit();
                }
            }
        }
        catch (System.Exception ex)
        {
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

This results in a Fatal Error.

I tried to lock the document, still Fatal Error.

I explored the AutoCADNodes.dll which is part of Dynamo for Civil 3D, there is one common function to create AutoCAD entities and as far as I understand it works the same way as my code above.

Why do I get a Fatal Error?

1 Like

Hey,

Welcome to the forum :slight_smile:

I’m not aware of many nodes which export points to cad, there is one in RIE which does so using a python script? Perhaps you can translate…

image

image

image

I’d be very interested in seeing your node for Civil 3D, would you be ok to upload it? :slight_smile:

Thanks,

Mark

What is the fatal error?

0x00040 if I remember well.

After a bit further testing it seems the error is not inside my function. I have not figured out how to debug, when I start a debug session then Dynamo is not loaded in Civil 3D. I used a workaround to show messages after each code line and it works even after a transmit and I can see the points formed in AutoCAD. But when that is done, a Fatal Error pops up and then I can’t do anything.

It’s for testing purpose, since Civil 3D 2020 has Dynamo (but very limited in nodes) so I was interested in creating new nodes to do funny things. It works quite well as far as it is querying and creating Dynamo geometry, but I would like to create AutoCAD objects as well (and off course Civil 3D objects).

When I’m a bit further I can post some code or dll.

That would be great, at the minute I have to import DWGs exported from Civil 3D then make a topo in Revit… I’d much rather go straight from Civil to Revit using Dynamo…

@Mark.Ackerley - The Civil3D instance of Dynamo runs inside of Civil 3D, so you won’t have access to the Revit API. AutoCAD’s .net api does allow for processing content from inside Dynamo for Revit though. The LinkDWG package does this for many objects but I have not tried topography. Linking directly from Civil3D into Revit has been VERY helpful for a lot of people I have worked with though - see this link for info: Link Topography

2 Likes

@Anton_Huizinga can you confirm if the graph is executing in manual or automatic run mode?

If it’s in Automatic, toggle it to manual and see if that helps.

If so it may be a document issue similar to the Revit case noted in this Dynamo for Revit GitHub issue: Returning Autodesk.Revit.DB.Document results in crash if the document is lost · Issue #2582 · DynamoDS/DynamoRevit · GitHub

It is running manual mode. I can’t relate the info in your link to my problem, unfortunately.

While in Dynamo it works perfectly, like this example where I simplify a heavy Civil 3D Surface:

But the node at the very right where I want to place DBPoints back in the drawing I get a 0x0040 Fatal Error. It happens after my function ends, because the points are created in the drawing. I can recover the drawing after the crash and it contains the created points.

I’ll try to create a test dll and drawing if someone wants to test.

If I create AutoCAD entities with the functions Dynamo provide, it works perfectly. I can create a 3D polyline without trouble.

Aren’t there examples for C# how to add AutoCAD entities in the drawing? Searching examples returns only examples how to get info into Dynamo, not the way back.

Here you can download an example:

https://a360.co/2PwA1zE

It is a zip that contains a Civil 3D drawing with a large Surface, the DEM file for that Surface, the Dynamo script and my DLL that can be added to Dynamo.

The full code of the node where the DBPoints are created is this:

  public static IList<string> CreateDBPoints(Autodesk.AutoCAD.DynamoNodes.Document document, List<Point> points)
    {
        IList<string> returnValue = new List<string>();

        using (dynAppServ.DocumentContext ctx = new dynAppServ.DocumentContext(document.AcDocument))
        {
            using (acDbServ.Transaction tr = ctx.Transaction)
            {
                acDbServ.BlockTableRecord currentSpace = (acDbServ.BlockTableRecord)tr.GetObject(ctx.Database.CurrentSpaceId, acDbServ.OpenMode.ForWrite);

                int pointNumber = 0;

                foreach (Point point in points)
                {
                    acDbServ.DBPoint node = new acDbServ.DBPoint(new Point3d(point.X, point.Y, point.Z));
                    node.SetDatabaseDefaults();
                    node.Layer = "0";
                    returnValue.Add((++pointNumber).ToString());
                    currentSpace.AppendEntity(node);
                    tr.AddNewlyCreatedDBObject(node, true);
                }
                tr.Commit();
            }
        }
        return returnValue;
    }

I can’t see anything wrong with that.

Ok, found it…

In my method as a few posts above I dispose the transaction. If I rewrite the method like this:

public static IList<string> CreateDBPoints(Autodesk.AutoCAD.DynamoNodes.Document document, List<Point> points)
{
    IList<string> returnValue = new List<string>();

    using (dynAppServ.DocumentContext ctx = new dynAppServ.DocumentContext(document.AcDocument))
    {

        acDbServ.Transaction tr = ctx.Transaction;

        using (acDbServ.BlockTableRecord currentSpace = (acDbServ.BlockTableRecord)tr.GetObject(ctx.Database.CurrentSpaceId, acDbServ.OpenMode.ForWrite))
        {
            int pointNumber = 0;
            foreach (Point point in points)
            {
                acDbServ.DBPoint node = new acDbServ.DBPoint(new Point3d(point.X, point.Y, point.Z));
                node.SetDatabaseDefaults();
                node.Layer = "0";
                returnValue.Add((++pointNumber).ToString());
                currentSpace.AppendEntity(node);
                tr.AddNewlyCreatedDBObject(node, true);
            }
        }
        tr.Commit();
    }
    return returnValue;
}

Then everything works like a charm. No Fatal Error.

Maybe the DocumentContext.Transaction is a top transaction or so, and disposing that is killing Dynamo. I’m not sure. I can dispose the DocumentContext, the Modelspace, everything, but NOT the Transaction.

Hope it will help others who stumble over this problem :slight_smile:

3 Likes

Probably a bit late :slight_smile: Should have checked the forum earlier. Disposing the transaction is one, and you also don’t need to commit it, though it doesn’t hurt .

Hello
Can you share the full Python Script?
I am a beginner
I don’t know how to add it to the Python Script

Do you have another example of how we use language C# in dynamo?

Thank

My code is not Python but C#. There are many examples of Python which creates AutoCAD geometry. You can search for that and start to learn from the examples.

Thanks
I will try
Thanks