Customization for Autocad, Civil 3D, and 3ds Max

Below are various thoughts / notes concerning customization of software and languages I use on a consistent basis. In most cases this includes Maxscript for 3ds Max and Autolisp / C#.Net for Autocad and Civil 3D.

It’s possible to edit the visibility states of dynamic blocks using c# .net.  For the flip state it was particularly tricky to deal with the short value.  I found by simply converting the object to a string I was able to easily swap between the states I wanted.  The code is below:

    DynamicBlockReferencePropertyCollection pc = br.DynamicBlockReferencePropertyCollection;
                            foreach (DynamicBlockReferenceProperty prop in pc)
                            {
                                if (prop.PropertyName.ToUpper().Contains("FLIP"))
                                {
                                    object[] allowedValues = prop.GetAllowedValues();
                                    if (prop.Value.ToString() == "1")
                                        prop.Value = allowedValues[0];
                                    else
                                        prop.Value = allowedValues[1];
                                }
                            }

1) I created a cheat sheet to help those learning the API for Civil 3D. You’re welcome to download it here:  Pro-Cad Civil 3D 2018 C-Sharp Net Cheat Sheet 

cheatsheet
2) Three reasons to learn to code:

Influence the Future – Imagine yourself born in 1452. Without a formal education you venture out to make a life. Instead, you shape the world. That’s exactly what Leonardo da Vinci did. He became the leader at the forefront of technology, shaping the world that followed. Da Vinci kept a massive journal filled with his ideas and sketches. He didn’t know his work would influence the world for centuries to come. Imagine the internet your journal, you are Da Vinci, and your code could do the same thing. “It had long since come to my attention that people of accomplishment rarely sat back and let things happen to them. They went out and happened to things.” – Leonardo da Vinci

A Challenge Worth Tackling – People refered to Da Vinci as a quiet man of science. Society called him a peaceful man, who did not approve of conflict and war. Yet, he understood the ‘bestialissimapazzia’ (most bestial madness) of war had two sides. The challenge he tackled was to protect his fellow man. He sought to maintain liberty from tyrants who would besiege them and their towns. Driven by a cause, he proceeded to investigate ways to protect them. This led to his studies into machinery and flight centuries ahead of its time. In the coding world there are two sides to the war. One is automation will replace humans and the quality of society will plumit. The opposing view is coding will lead to improvements by allowing people to focus on being more creative and caring. It’s a choice to believe one or the other, and coding isn’t going away. ” Every action needs to be prompted by a motive” – Leonardo da Vinci

Improve Life – Da Vinci noted that simplicity is the ultimate sophistication. He ventured to improve the lives around him while studying and learning what he loved. He found the two functions were the same. In the end, if our efforts help to make one or two lives more easier to manage, it’s an improvement. Chances are, if you are reading this, you have a fetish for Da Vinci or you are interested in coding. I can’t help with the former but the latter is shaping the world as we know it, we just need to get on bored. “A painter was asked why he had made his children so ugly, when his figures which were dead things he had made so beautiful. His reply was that he made his pictures by day and his children at night.” – A Joke by Leonardo da Vinci

The sharp symbol in C# is a reference to the music note, and that it combines four + symbols to create it.

3) General Resources

Coding Haven – http://www.c-sharpcorner.com/technologies/csharp-programming

Civil 3D/Autocad

Development Guide – http://help.autodesk.com/view/CIV3D/2017/ENU/?guid=GUID-275A6271-7758-4C14-9703-989B1B007E3E

3ds Max

CGSchool Maxscript Cheat Sheet – http://www.thecgschool.com/downloads/3DATS_MAXScript_Cheat_Sheet.pdf

4) Using C# .Net with Autocad or Civil 3D it’s easy to dynamically construct a winform and datagridview to display information we might want inside a drawing.  This example demonstrates how to do that by listing the number of objects inside the BlockTableRecord for modelspace.

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using System.Linq;
using System.Windows.Forms;

namespace Autocad_DataGridView
{
    public class Class1
    {
        [CommandMethod("acadgridview")]
        public void routine()
        {

            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                ObjectId modelSpaceId = SymbolUtilityServices.GetBlockModelSpaceId(db);
                BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                BlockTableRecord btr = tr.GetObject(modelSpaceId, OpenMode.ForRead) as BlockTableRecord;

                Form form = new Form();
                form.Width = 300;
                form.Show();

                DataGridView MyDataGridView = new DataGridView();
                MyDataGridView.Anchor = AnchorStyles.Top;
                MyDataGridView.Width = form.Width;
                MyDataGridView.Height = form.Height;
                MyDataGridView.Columns.Add("Column 1", "Objects In Model Space");
                MyDataGridView.Rows.Add(btr.Cast<ObjectId>().Count().ToString());
                MyDataGridView.Columns[0].Width = form.Width;
                form.Controls.Add(MyDataGridView);

            }
        }
    }
}

5) Everything we program in regards to Civil 3D or Autocad requires we collect and work with data. In some cases we wish to produce reports and tables of information. Using C# with the Civil 3D API we can do this on the fly. Below is an example. First I create a form dynamically. Then I collect the layers (SymbolTable) where I add columns for the layer name and the layer color.  Next, I iterate through the layers in the Symbol Table and add them to the DataTable that was created dynamically.  Finally, I create a DataGridView to display the information I stored in the DataTable, since the DataTable can’t be displayed in it’s native format.

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using System.Windows.Forms;

namespace Autocad_DataTable
{
    public class Class1
    {
        [CommandMethod("acaddatatable")]
        public void routine()
        {

            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                Form form = new Form();
                form.Width = 300;

                SymbolTable symboltable = (SymbolTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead); 

                System.Data.DataTable dt = new System.Data.DataTable();
                dt.Columns.Add("Layer Name");
                dt.Columns.Add("Layer Color");

                foreach (ObjectId id in symboltable)
                {
                    LayerTableRecord symbol = (LayerTableRecord)tr.GetObject(id, OpenMode.ForRead);

                    System.Data.DataRow dr = dt.Rows.Add();
                    dr["Layer Name"] = symbol.Name;
                    dr["Layer Color"] = symbol.Color.ToString();
                }

                DataGridView grid = new DataGridView();
                form.Controls.Add(grid);
                grid.DataSource = dt;
                form.Show();
            }
        }
    }
}

6) One of the most important parts of customization is optimization. For example, if we want to change some featurelines we don’t want to iterate through the drawing’s entire database. Instead, we  filter everything out and start with the featurelines.  Eventually we drill down until we get those we want to modify, but to begin we use selection filters (shown here: Dev Guide Link).  In order to use selection filters we need to know the DXFCode (or DXF Name) of the object we wish to select. One way find this out is to cast the modelspace objects to a list, then print a list of those objects dxf names to the screen using a  DataGridView as shown in the example below.

dxfnames

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using System.Linq;
using System.Windows.Forms;

namespace Autocad_DataGridView
{
    public class Class1
    {
        [CommandMethod("acaddxftotal")]
        public void routine()
        {

            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                ObjectId modelSpaceId = SymbolUtilityServices.GetBlockModelSpaceId(db);
                BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                BlockTableRecord btr = tr.GetObject(modelSpaceId, OpenMode.ForRead) as BlockTableRecord;

                Form form = new Form();
                form.Width = 700;
                form.Show();

                System.Collections.Generic.List<string> dxfnames = new System.Collections.Generic.List<string>();

                DataGridView MyDataGridView = new DataGridView();
                MyDataGridView.Anchor = AnchorStyles.Top;
                MyDataGridView.Width = form.Width;
                MyDataGridView.Height = form.Height;
                MyDataGridView.Columns.Add("Column 1", "DXF Names");
                System.Collections.Generic.List<ObjectId> modelspaceobjects = btr.Cast<ObjectId>().ToList();
                foreach (ObjectId modelobjectid in modelspaceobjects)
                {
                    dxfnames.Add(modelobjectid.ObjectClass.DxfName.ToString());
                }

                System.Collections.Generic.List<string> distinctdxfnames = dxfnames.Distinct().ToList();
                foreach (string dxfname in distinctdxfnames)
                {
                    MyDataGridView.Rows.Add(dxfname);
                }
                MyDataGridView.Columns[0].Width = form.Width;
                form.Controls.Add(MyDataGridView);

            }
        }
    }
}

7) Link to probably the best example of using linq with autocad: Linq and the Autocad Net API

8) Several years ago I decided to abandon the two script / program languages I was using and forced myself to learn a new one (just to see if I could really). That was C# (C-Sharp). This chart shows that it’s top of the line to take of the world. Lotto XD

CcVyDI9UsAA0RQp.jpg large

9) A completely useless app but I had fun developing it. If you want it just message I’ll send it your way.

10) Here’s a cool idea.  With the ability to use animated gifs in picture boxes we can develop training applications in CAD for specific workflows.  Check out an animated interface I created here: https://www.youtube.com/watch?v=y391aP_jCeE&feature=youtu.be&vq=hd720

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s