Alignments — creation, entities, stations, design speeds, superelevation
Use this skill when creating, modifying, or querying alignments, working with stations, or configuring superelevation.
// All alignments (siteless + sited)
ObjectIdCollection allAlignments = doc.GetAlignmentIds();
// Only siteless alignments
ObjectIdCollection sitelessAlignments = doc.GetSitelessAlignmentIds();
// Overload 1: By name strings (pass "" for siteless)
ObjectId alignId = Alignment.Create(doc, "New Alignment",
"", // site name ("" = siteless)
"0", // layer name
"Basic", // alignment style name
"AllLabels" // label set style name
);
// Overload 2: By ObjectIds (pass ObjectId.Null for siteless)
ObjectId alignId = Alignment.Create(doc, "New Alignment",
ObjectId.Null, // siteId (Null = siteless)
layerId, // ObjectId of layer
styleId, // ObjectId of alignment style
labelSetId // ObjectId of label set style
);
// Overload 3: By ObjectIds with explicit AlignmentType
ObjectId alignId = Alignment.Create(doc, "New Alignment",
ObjectId.Null, layerId, styleId, labelSetId,
AlignmentType.Centerline
);
PromptEntityOptions opt = new PromptEntityOptions("\nSelect a polyline");
opt.SetRejectMessage("\nObject must be a polyline.");
opt.AddAllowedClass(typeof(Polyline), false);
PromptEntityResult res = ed.GetEntity(opt);
PolylineOptions plops = new PolylineOptions();
plops.AddCurvesBetweenTangents = true;
plops.EraseExistingEntities = true;
plops.PlineId = res.ObjectId;
// String overload
ObjectId alignId = Alignment.Create(doc, plops,
"New Alignment", "MySite", "0", "Standard", "Standard");
// ObjectId overload
ObjectId alignId = Alignment.Create(doc, plops,
"New Alignment", siteId, layerId, styleId, labelSetId);
ObjectId alignId = Alignment.Create(corridorFeatureLine,
"FL Alignment", siteId, layerId, styleId, labelSetId,
AlignmentType.Centerline);
The instance method CreateOffsetAlignment(double) is deprecated since Civil 3D 2010. Use the static overloads instead:
// By name strings (full station range)
ObjectId offsetId = Alignment.CreateOffsetAlignment(db,
"Offset Align", // new alignment name
"Parent Alignment", // parent alignment name
10.0, // offset distance (positive = right)
"Standard" // style name
);
// By name strings (partial station range)
ObjectId offsetId = Alignment.CreateOffsetAlignment(db,
"Offset Align", "Parent Alignment", 10.0, "Standard",
100.0, 500.0 // startStation, endStation
);
// By ObjectIds (full station range)
ObjectId offsetId = Alignment.CreateOffsetAlignment(
"Offset Align", parentAlignId, 10.0, styleId);
// By ObjectIds (partial station range)
ObjectId offsetId = Alignment.CreateOffsetAlignment(
"Offset Align", parentAlignId, 10.0, styleId, 100.0, 500.0);
ObjectId connectedId = Alignment.CreateConnectedAlignment(
"Connected Align", siteId, layerId, styleId, labelSetId,
connectedAlignmentParams);
// Check if an alignment is connected
bool isConnected = align.IsConnectedAlignment;
ConnectedAlignmentInfo info = align.ConnectedAlignmentInfo;
// Copy to a named site
align.CopyToSite("MySite");
// Copy by site ObjectId
align.CopyToSite(siteId);
// Copy within the same site
align.CopyToSameSite();
Entities are lines, curves, and spirals that form the alignment path. The collection supports fixed, floating, and free constraint types.
AlignmentEntityCollection entities = align.Entities;
foreach (AlignmentEntity ae in align.Entities)
{
switch (ae.EntityType)
{
case AlignmentEntityType.Arc:
AlignmentArc myArc = ae as AlignmentArc;
ed.WriteMessage("Arc R={0}, L={1}\n", myArc.Radius, myArc.Length);
break;
case AlignmentEntityType.Line:
AlignmentLine myLine = ae as AlignmentLine;
ed.WriteMessage("Line dir={0}\n", myLine.Direction);
break;
case AlignmentEntityType.Spiral:
AlignmentSpiral mySpiral = ae as AlignmentSpiral;
ed.WriteMessage("Spiral A={0}\n", mySpiral.A);
break;
// Also: SpiralCurve, SpiralSpiral, SpiralCurveSpiralCurveSpiral, etc.
}
}
AlignmentEntity entity = entities.EntityAtId(entityId); // by entity ID
AlignmentEntity entity = entities.GetEntityByOrder(index); // by draw order
AlignmentEntity entity = entities.EntityAtStation(rawStation); // by station
int first = entities.FirstEntity; // ID of first entity
int last = entities.LastEntity; // ID of last entity
// Fixed lines
AlignmentLine line = entities.AddFixedLine(startPoint, endPoint);
AlignmentLine line = entities.AddFixedLine(prevEntityId, startPoint, endPoint);
AlignmentLine line = entities.AddFixedLine(prevEntityId, distance);
// Fixed curves (many overloads)
AlignmentArc arc = entities.AddFixedCurve(prevEntityId, startPt, midPt, endPt);
AlignmentArc arc = entities.AddFixedCurve(pt1, pt2, radius, isClockwise);
AlignmentArc arc = entities.AddFixedCurve(centerPt, passThroughPt, isClockwise);
AlignmentArc arc = entities.AddFixedCurve(centerPt, radius, isClockwise);
AlignmentArc arc = entities.AddFixedCurve(pt1, dirAtPt1, radius, isClockwise);
AlignmentArc arc = entities.AddFixedCurve(pt1, dirAtPt1, pt2);
AlignmentArc arc = entities.AddFixedCurve(pt1, pt2, dirAtPt2);
// Fixed spirals
AlignmentSpiral sp = entities.AddFixedSpiral(prevId, startRadius, endRadius, length, spiralDef);
AlignmentSpiral sp = entities.AddFixedSpiral(prevId, radius, length, spiralCurveType, spiralDef);
AlignmentSpiral sp = entities.AddFixedSpiral(prevId, startPt, piPt, endPt, spiralDef);
// Floating lines
AlignmentLine line = entities.AddFloatingLine(prevEntityId, length);
AlignmentLine line = entities.AddFloatingLine(prevEntityId, passThroughPt);
AlignmentLine line = entities.AddFloatingLine(length, nextEntityId);
// Floating curves
AlignmentArc arc = entities.AddFloatingCurve(prevEntityId, passThroughPt);
AlignmentArc arc = entities.AddFloatingCurve(prevEntityId, radius, paramValue,
paramType, isClockwise);
// Free line between two entities
AlignmentLine line = entities.AddFreeLine(prevEntityId, nextEntityId);
// Free curve between two entities
AlignmentArc arc = entities.AddFreeCurve(prevEntityId, nextEntityId,
passThroughPt);
AlignmentArc arc = entities.AddFreeCurve(prevEntityId, nextEntityId,
paramValue, paramType, isGreaterThan180, curveType);
// Free spiral-curve-spiral
AlignmentSCS scs = entities.AddFreeSCS(prevEntityId, nextEntityId,
sp1Param, sp2Param, spType, radius, isGreaterThan180, spiralDef);
entities.Remove(entity);
entities.RemoveAt(index);
entities.Clear();
StationEquation eq = align.StationEquations.Add(
80, // rawStationBack: raw station value at the equation point (distance from start)
0, // stationAhead: station value assigned going ahead past the equation
StationEquationType.Increasing
);
StationTypes is a flags enum (note the plural). Common values: All, Major, Minor, GeometryPoint, Equation, SuperTransPoint.
// Get all stations with major=100, minor=20
Station[] stations = align.GetStationSet(StationTypes.All, 100, 20);
foreach (Station s in stations)
{
ed.WriteMessage("Station {0}, Type: {1}, Location: ({2},{3})\n",
s.RawStation, s.StationType, s.Location.X, s.Location.Y);
}
// Major stations only, single interval
Station[] majors = align.GetStationSet(StationTypes.Major, 100);
// Geometry points only (no interval needed)
Station[] geoPts = align.GetStationSet(StationTypes.GeometryPoint);
// Custom range with major=50, minor=10
Station[] ranged = align.GetStationSet(StationTypes.All, 50, 10, 100.0, 500.0);
// Simple version: station + offset -> easting + northing
double easting, northing;
align.PointLocation(station, offset, ref easting, ref northing);
// With tolerance and bearing
double bearing;
align.PointLocation(station, offset, tolerance,
ref easting, ref northing, ref bearing);
Tolerance note: Determines which entity the point is on. A large tolerance may place the point on an earlier entity. Note parameter order is easting, northing (X, Y).
// Simple version: easting + northing -> station + offset
double station, offset;
align.StationOffset(easting, northing, ref station, ref offset);
// With tolerance
align.StationOffset(easting, northing, tolerance, ref station, ref offset);
// Accept out-of-range points (beyond alignment start/end)
bool outOfRange;
align.StationOffsetAcceptOutOfRange(easting, northing,
ref station, ref offset, ref outOfRange);
// With tolerance + out-of-range
align.StationOffsetAcceptOutOfRange(easting, northing, tolerance,
ref station, ref offset, ref outOfRange);
// Get the radius at a specific raw station value
// Returns double.PositiveInfinity for tangent segments
double radius = align.GetInstantaneousRadius(rawStation);
// Reverses the direction of the alignment geometry
align.Reverse();
double distToOther, stationOnOther;
align.DistanceToAlignment(stationOnThis, otherAlignment,
ref distToOther, ref stationOnOther);
// With explicit side
align.DistanceToAlignment(stationOnThis, otherAlignment,
AlignmentSide.Left, ref distToOther, ref stationOnOther);
DesignSpeed ds = align.DesignSpeeds.Add(0, 45); // station 0+00, 45 mph
ds.Comment = "Straightaway";
ds = align.DesignSpeeds.Add(430, 30); // station 4+30
ds.Comment = "Start of curve";
align.UseDesignSpeed = true; // Enable speed-based design
Note: GetDesignSpeed() requires a "raw" station value (without station equation modifications).
Superelevation is divided into curves, each containing transition regions with critical stations.
// Access superelevation curves
if (align.SuperelevationCurves.Count < 1)
{
ed.WriteMessage("Must calculate superelevation data first.\n");
return;
}
foreach (SuperelevationCurve sec in align.SuperelevationCurves)
{
ed.WriteMessage("Curve: {0}, Start: {1}, End: {2}\n",
sec.Name, sec.StartStation, sec.EndStation);
foreach (SuperelevationCriticalStation sest in sec.CriticalStations)
{
ed.WriteMessage(" Station: {0}, Type: {1}, Region: {2}\n",
sest.Station, sest.StationType, sest.TransitionRegionType);
// Get slope for each cross segment type
foreach (int i in Enum.GetValues(typeof(SuperelevationCrossSegmentType)))
{
try
{
double slope = sest.GetSlope(
(SuperelevationCrossSegmentType)i);
ed.WriteMessage(" Slope: {0}, Segment: {1}\n", slope,
Enum.GetName(typeof(SuperelevationCrossSegmentType), i));
}
catch (InvalidOperationException) { } // Invalid segment type for this station
}
}
}
Key properties:
Alignment.SuperelevationCurves - collection of SE curvesAlignment.SuperelevationCriticalStations - all critical stations across all curvesSuperelevationCriticalStationCollection.GetCriticalStationAt() - access individual stationsAPI Change Note (Civil 3D 2013+): SuperelevationData property and SuperElevationAtStation() method were removed. Use SuperelevationCurves and SuperelevationCriticalStations instead.
ObjectId styleId = doc.Styles.AlignmentStyles.Add("My Alignment Style");
AlignmentStyle style = ts.GetObject(styleId, OpenMode.ForWrite) as AlignmentStyle;
// Hide direction arrows
style.GetDisplayStylePlan(AlignmentDisplayStyleType.Arrow).Visible = false;
// Show curves in violet
style.GetDisplayStylePlan(AlignmentDisplayStyleType.Curve).Color =
Color.FromColorIndex(ColorMethod.ByAci, 200);
// Show lines in blue
style.GetDisplayStylePlan(AlignmentDisplayStyleType.Line).Color =
Color.FromColorIndex(ColorMethod.ByAci, 160);
// Assign to alignment
align.StyleId = style.Id;
Labels are set via LabelSet when creating an alignment, or through LabelSetStyles:
// Label set styles
var labelSetStyles = doc.Styles.LabelSetStyles.AlignmentLabelSetStyles;
// AlignmentLabelSetItem types:
// LabelStyleType.AlignmentMajorStation
// LabelStyleType.AlignmentMinorStation
// Minor stations must reference a parent major station AlignmentLabelSetItem
Major/minor stations:
<[Station Value(Uft|FS|P0|RN|AP|Sn|TP|B2|EN|W0|OF)]>
<[Northing(Uft|P4|RN|AP|Sn|OF)]>
<[Design Speed(P3|RN|AP|Sn|OF)]>
<[Alignment Name(CP)]>
Additional fields for specific label types:
<[Offset From Major Station(...)]><[Geometry Point Text(CP)]>, <[Geometry Point Entity Before/After Data(CP)]><[Design Speed Before(...)]><[Station Ahead(...)]>, <[Station Back(...)]>, <[Increase/Decrease(CP)]>// Get profile views for this alignment
ObjectIdCollection pvIds = align.GetProfileViewIds();
// Get sample line groups
ObjectIdCollection slgIds = align.GetSampleLineGroupIds();
// Get profiles
ObjectIdCollection profileIds = align.GetProfileIds();
// Get superelevation views
ObjectIdCollection seViewIds = align.GetSuperelevationViewIds();
// Get child offset alignments
ObjectIdCollection offsetIds = align.GetChildOffsetAlignmentIds();
ObjectIdCollection dynamicOnly = align.GetChildOffsetAlignmentIds(true); // only dynamic-update offsets
// Get label group IDs
ObjectIdCollection labelGroupIds = align.GetAlignmentLabelGroupIds();
ObjectIdCollection labelIds = align.GetAlignmentLabelIds();
// Export to polyline
ObjectId plineId = align.GetPolyline();
// Import a label set
align.ImportLabelSet("My Label Set");
align.ImportLabelSet(labelSetStyleId);
// Get station string with equations applied
string stationStr = align.GetStationStringWithEquations(rawStation);
// Get next unique alignment name
string uniqueName = Alignment.GetNextUniqueName("MyAlignment");
// Alignment geometry range
double start = align.StartingStation;
double end = align.EndingStation;
double endEq = align.EndingStationWithEquations;
double length = align.Length;
// Reference point (station origin)
Point2d refPt = align.ReferencePoint;
double refStation = align.ReferencePointStation;
// Site info
string siteName = align.SiteName;
bool isSiteless = align.IsSiteless;
// Offset alignment info
bool isOffset = align.IsOffsetAlignment;
OffsetAlignmentInfo oaInfo = align.OffsetAlignmentInfo;
// Type and creation mode
AlignmentType aType = align.AlignmentType;
AlignmentCreationType cMode = align.CreationMode;
// Cross slope at station (superelevation)
// Valid values: LeftOutShoulderCrossSlope, LeftOutLaneCrossSlope, LeftInShoulderCrossSlope,
// LeftInLaneCrossSlope, RightOutShoulderCrossSlope, RightOutLaneCrossSlope,
// RightInShoulderCrossSlope, RightInLaneCrossSlope
double slope = align.GetCrossSlopeAtStation(station,
SuperelevationCrossSegmentType.LeftInLaneCrossSlope, true); // adjust side as needed
Create() string overload fails if the named styles don't exist in the documentGetStationStringWithEquations() for display)GetSlope() throws InvalidOperationException for invalid segment types - catch silentlyPointLocation and StationOffset parameter order is easting, northing (X, Y), not northing, eastingGetInstantaneousRadius() requires a raw station valueCreateOffsetAlignment(double) is deprecated since Civil 3D 2010; use the static overloadsStationTypes is a flags enum (plural) - use StationTypes.All, not StationType.Allc3d-profiles - Profiles along alignmentsc3d-label-styles - General label style creationc3d-corridors - Corridors use alignments as baselinesacad-editor-input - Selecting alignments with GetEntity and AddAllowedClassc3d-superelevation - Detailed superelevation data access, critical stations, and cross slopesc3d-intersections - Intersection objects at alignment crossings