| name | c3d-root-objects |
| description | CivilApplication, CivilDocument, transactions, settings hierarchy, locking |
Civil 3D Root Objects and Common Concepts
Use this skill when accessing base Civil 3D objects, working with transactions, iterating collections, or configuring settings.
Root Object Hierarchy
CivilApplication
└── ActiveDocument (CivilDocument)
├── GetAlignmentIds()
├── GetSitelessAlignmentIds()
├── GetSiteIds()
├── GetSurfaceIds()
├── GetPipeNetworkIds() ← gravity networks
├── GetPressurePipeNetworkIds() ← pressure networks
├── CorridorCollection
├── CogoPoints
├── PointGroups
├── Styles (StylesRoot)
│ ├── AlignmentStyles
│ ├── ProfileStyles
│ ├── ProfileViewStyles
│ ├── SurfaceStyles
│ ├── PipeStyles
│ ├── StructureStyles
│ ├── PointStyles
│ ├── InterferenceStyles
│ ├── AssemblyStyles
│ ├── LinkStyles
│ ├── ShapeStyles
│ ├── CodeSetStyles
│ ├── PartsListSet
│ ├── LabelStyles (all label style roots)
│ ├── LabelSetStyles
│ └── ProfileViewBandSetStyles
└── Settings (SettingsRoot)
├── DrawingSettings
└── GetSettings<T>()
Accessing Application and Document
using Autodesk.Civil.ApplicationServices;
CivilDocument doc = CivilApplication.ActiveDocument;
CivilDocument doc = CivilDocument.GetCivilDocument(database);
Note: CivilApplication does NOT inherit from AutoCAD's Application. For application-level access (open documents, main window), use Autodesk.AutoCAD.ApplicationServices.Application directly.
Transaction Pattern
All Civil 3D object reads/writes MUST be inside a Transaction:
using (Transaction ts = Application.DocumentManager.MdiActiveDocument
.Database.TransactionManager.StartTransaction())
{
Alignment align = ts.GetObject(alignId, OpenMode.ForRead) as Alignment;
align = ts.GetObject(alignId, OpenMode.ForWrite) as Alignment;
align.StyleId = newStyleId;
ts.Commit();
}
Best practice: Use using statement for automatic disposal. Otherwise, explicitly dispose in a finally block.
ObjectId Collections
Collections return ObjectIdCollection (not typed objects). You must cast via Transaction.GetObject():
ObjectIdCollection alignmentIds = doc.GetAlignmentIds();
foreach (ObjectId objId in alignmentIds)
{
Alignment align = ts.GetObject(objId, OpenMode.ForRead) as Alignment;
ed.WriteMessage("Alignment: {0}\n", align.Name);
}
Creating Styles
ObjectId styleId = doc.Styles.PointStyles.Add("MyStyle");
PointStyle style = ts.GetObject(styleId, OpenMode.ForWrite) as PointStyle;
style.Elevation = 114.6;
ts.Commit();
Handling Duplicate Names
try
{
ObjectId styleId = doc.Styles.PointStyles["Name"];
}
catch (ArgumentException e)
{
ed.WriteMessage(e.Message);
}
Document Locking (for Modeless Forms / Toolbox)
When code runs outside document context (modeless dialogs, .NET toolbox execution), explicitly lock the document:
using (DocumentLock locker = Application.DocumentManager
.MdiActiveDocument.LockDocument())
{
CivilApplication.ActiveDocument.Settings
.DrawingSettings.AmbientSettings.Station.Precision.Value = 2;
}
Settings Hierarchy
Settings apply at three levels (each can override the previous):
- Drawing level -
doc.Settings.DrawingSettings (units, zone, abbreviations, ambient settings)
- Feature level -
doc.Settings.GetSettings<SettingsAlignment>() (overrides drawing ambient for that feature)
- Command level -
doc.Settings.GetSettings<SettingsCmdCreateAlignmentLayout>() (overrides both)
SettingsAlignment alignSettings = doc.Settings.GetSettings<SettingsAlignment>();
var angleSettings = alignSettings.Angle;
ed.WriteMessage("Precision: {0}, Unit: {1}\n",
angleSettings.Precision.Value, angleSettings.Unit.Value);
SettingsCmdCreateAlignmentLayout cmdSettings =
doc.Settings.GetSettings<SettingsCmdCreateAlignmentLayout>();
ed.WriteMessage("AlignmentType: {0}",
cmdSettings.AlignmentTypeOption.AlignmentType.Value);
Note: Feature and command settings are in Autodesk.Civil.Settings — the same namespace as drawing/ambient settings. There is no separate Autodesk.Civil.Land.Settings namespace.
Property Value Pattern
In the .NET API, most properties use Property* classes implementing IProperty. Access values via .Value:
Error Handling Pattern
[CommandMethod("MYCOMMAND")]
public void MyCommand()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
try
{
using (Transaction ts = ...)
{
ts.Commit();
}
}
catch (System.Exception e)
{
ed.WriteMessage("\nError: {0}\n", e.Message);
}
}
Surface Namespace Conflict
Surface exists in both Autodesk.AutoCAD.DatabaseServices and Autodesk.Civil.DatabaseServices. Disambiguate with alias:
using CivSurface = Autodesk.Civil.DatabaseServices.Surface;
Gotchas
- Adding an element with a duplicate name throws an error - trap it
- Accessing a non-existent item throws
ArgumentException
- Removing an in-use item throws an error
ObjectIdCollection implements IList - can use foreach or index access
- Properties in .NET use
.Value getter/setter (unlike COM's direct property access)
- Some properties have moved to sub-properties (e.g.,
Visibility -> General.Visible)
Related Skills
c3d-project-setup - Project configuration and references
c3d-label-styles - Label style creation and components
c3d-pipe-networks - Gravity and pressure pipe networks (accessed via GetPipeNetworkIds / GetPressurePipeNetworkIds)
c3d-sample-lines - Sample line groups and section views (accessed via alignment)