In large Civil 3D projects, managing pipe network labels can become time-consuming, especially when styles or properties need to be updated across multiple pipes. Automating this process using C# and the Civil 3D API can significantly improve productivity.
Problem Overview
When working with pipe networks, labels may become inconsistent due to:
- Manual edits by different users
- Changes in label styles
- Updates to pipe properties (diameter, slope, invert levels)
The goal is to synchronize pipe labels so that all pipes follow a consistent style and updated data.
Approach
Using the Civil 3D .NET API, we can:
- Access all pipe networks in the drawing
- Iterate through each pipe
- Find and update associated labels
- Apply a standard label style
Basic Setup
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.Civil.ApplicationServices;
using Autodesk.Civil.DatabaseServices;
Command Structure
[CommandMethod("PN_MAPipeLabel")]
[Obsolete]
public void JigPipelabel()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
CivilDocument civil = CivilApplication.ActiveDocument;
try
{
using (DocumentLock aclock = doc.LockDocument())
{
using (Transaction _tr = db.TransactionManager.StartTransaction())
using (_tr)
{
#region Ống làm chuẩn
//
PromptEntityOptions _ent = new PromptEntityOptions("\nSelect Pipe label typical:");
_ent.SetRejectMessage("Must be PipeElevationLabel");
_ent.AddAllowedClass(typeof(PipeLabel), true);
PromptEntityResult _ents = ed.GetEntity(_ent);
if (_ents.Status != PromptStatus.OK)
return;
ObjectId _EDS = _ents.ObjectId;
PipeLabel _Pipe = _tr.GetObject(_EDS, OpenMode.ForWrite) as PipeLabel;
var _local = _Pipe.DraggedOffset;
#endregion
#region Ống cần xoay
//
TypedValue[] _tv = new TypedValue[1] { new TypedValue((int)DxfCode.Start, "AECC_PIPE_LABEL") };
SelectionFilter _ts = new SelectionFilter(_tv);
PromptSelectionOptions _op = new PromptSelectionOptions();
_op.MessageForAdding = "Select Pipe label to typical:";
PromptSelectionResult _ops = ed.GetSelection(_op, _ts);
if (_ops.Status != PromptStatus.OK)
return;
ObjectId[] _IDS = _ops.Value.GetObjectIds();
#endregion
foreach (ObjectId _id in _IDS)
{
PipeLabel _Pipes = _tr.GetObject(_id, OpenMode.ForWrite) as PipeLabel;
_Pipes.LabelLocation = _Pipes.AnchorInfo.Location.TransformBy(Matrix3d.Displacement(_local));
_Pipes.DraggedOffset = _local;
}
_tr.Commit();
}
}
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
ed.WriteMessage("\nError: " + ex.Message);
return;
}
}
Core Logic (To Be Implemented)
// ================= YOUR CODE HERE =================
// Example ideas:
// - Loop through PipeNetworks
// - Get all Pipes
// - Check existing labels
// - Remove or update labels
// - Apply a standard label style
// ================================================
Tips & Best Practices
- Always wrap database operations inside a Transaction
- Use ObjectId collections for better performance
- Validate label existence before creating new ones
- Consider handling Profile View labels separately
Conclusion
Automating pipe label synchronization in Civil 3D using C# is a powerful way to ensure consistency and reduce manual work. With a well-structured command, you can easily scale this solution across large projects.
Feel free to extend this approach by adding UI (WinForms/WPF) or integrating with BIM workflows.
