- Published on
1 - Project Polyline From Profile View
- Authors
- Name
- Matheus Ramos
Introduction
When adjusting surfaces, one of the main challenges in my work is to performing this adjustment quickly and accurately. The lack of a command that allows me to draw directly in the Profile View and thus create a 3D Polyline at the desired location to use as a Breakline on the surface motivated me to develop the following command using the Civil 3D C# API.
With this command, I can draw a polyline directly on the profile view and then project that polyline as a 3D polyline to use as a Breakline on the surface. To develop this command the following steps were necessary:
- Select a polyline.
- Select a profile view.
- Create an empty profile.
- Extract the geometry information from the Polyline and add it to the empty Profile.
- Create an empty 3D polyline.
- Obtain the alignment associated with the profile view to extract the easting and northing coordinates.
- Go through the PVIs (Points of Vertical Intersection) of the profile.
- Add the PVI coordinates and elevations to the 3D Polyline.
- Add the 3D polyline to the model and Delete Profile.
Below, I will explain each step with the accompanying code.
- Select an existing polyline.
PromptEntityOptions promptPolyline = new PromptEntityOptions("\nSelect a Polyline: ");
promptPolyline.SetRejectMessage("\n Polyline not Select");
promptPolyline.AddAllowedClass(typeof(Polyline), true);
PromptEntityResult entityPolyline = editor.GetEntity(promptPolyline);
if (entityPolyline.Status != PromptStatus.OK) return;
- Select a profile view
PromptEntityOptions promptProfileView = new PromptEntityOptions("\nSelect a profile view: ");
promptProfileView.SetRejectMessage("\nProfileView not select");
promptProfileView.AddAllowedClass(typeof(ProfileView), true);
PromptEntityResult entityProfileView = editor.GetEntity(promptProfileView);
if (entityProfileView.Status != PromptStatus.OK) return;
- Create an empty profile.
ProfileView profileView = tx.GetObject(entityProfileView.ObjectId, OpenMode.ForWrite) as ProfileView;
double x = 0.0;
double y = 0.0;
if (profileView.ElevationRangeMode == ElevationRangeType.Automatic)
{
profileView.ElevationRangeMode = ElevationRangeType.UserSpecified;
profileView.FindXYAtStationAndElevation(profileView.StationStart, profileView.ElevationMin, ref x, ref y);
}
else
profileView.FindXYAtStationAndElevation(profileView.StationStart, profileView.ElevationMin, ref x, ref y);
ProfileViewStyle profileViewStyle = tx.GetObject(profileView.StyleId, OpenMode.ForRead) as ProfileViewStyle;
ObjectId layerId = (tx.GetObject(profileView.AlignmentId, OpenMode.ForRead) as Alignment).LayerId;
ObjectId profileStyleId = doc.Styles.ProfileStyles.FirstOrDefault();
ObjectId profileLabelSetStylesId = doc.Styles.LabelSetStyles.ProfileLabelSetStyles.FirstOrDefault();
ObjectId profByLayout = Profile.CreateByLayout("New Profile", profileView.AlignmentId, layerId, profileStyleId, profileLabelSetStylesId);
Profile profile = tx.GetObject(profByLayout, OpenMode.ForWrite) as Profile;
BlockTableRecord blockTableRecord = tx.GetObject(database.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
- Extract the geometry information from the Polyline and add it to the empty Profile.
ObjectId polylineObjId = entityPolyline.ObjectId;
Polyline polyline = tx.GetObject(polylineObjId, OpenMode.ForWrite, false) as Polyline;
double intervalMajorTick = profileViewStyle.BottomAxis.MajorTickStyle.Interval;
double gridPadding = profileViewStyle.GridStyle.GridPaddingLeft * intervalMajorTick;
//Invert the Polyline if the start coordinate is greater than the end coordinate
if (polyline != null && (polyline.StartPoint.X > polyline.EndPoint.X))
{
polyline.ReverseCurve();
}
if (polyline != null)
{
int numOfVert = polyline.NumberOfVertices - 1;
Point2d startSegment;
Point2d endSegment;
Point2d sampleSegment;
Point2d coodStartSeg;
Point2d coodEndSeg;
Point2d coodSampleSegment;
for (int i = 0; i < numOfVert; i++)
{
switch (polyline.GetSegmentType(i))
{
case SegmentType.Line:
LineSegment2d lineSegment2dAt = polyline.GetLineSegment2dAt(i);
startSegment = lineSegment2dAt.StartPoint;
double difStartSegment_X = (startSegment.X - gridPadding) - x;
double difStartSegment_Y = (startSegment.Y - y) / profileViewStyle.GraphStyle.VerticalExaggeration + profileView.ElevationMin;
coodStartSeg = new Point2d(difStartSegment_X, difStartSegment_Y);
endSegment = lineSegment2dAt.EndPoint;
double difEndSegment_X = (endSegment.X - gridPadding) - x;
double difEndSegment_Y = (endSegment.Y - y) / profileViewStyle.GraphStyle.VerticalExaggeration + profileView.ElevationMin;
coodEndSeg = new Point2d(difEndSegment_X, difEndSegment_Y);
profile.Entities.AddFixedTangent(coodStartSeg, coodEndSeg);
break;
case SegmentType.Arc:
CircularArc2d arcSegment2dAt = polyline.GetArcSegment2dAt(i);
startSegment = arcSegment2dAt.StartPoint;
double difStartSegmentArc_x = (startSegment.X - gridPadding) - x;
double difStartSegmentArc_y = (startSegment.Y - y) / profileViewStyle.GraphStyle.VerticalExaggeration + profileView.ElevationMin;
coodStartSeg = new Point2d(difStartSegmentArc_x, difStartSegmentArc_y);
endSegment = arcSegment2dAt.EndPoint;
double difEndSegmentArc_x = endSegment.X - gridPadding - x;
double difEndSegmentArc_y = (endSegment.Y - y) / profileViewStyle.GraphStyle.VerticalExaggeration + profileView.ElevationMin;
coodEndSeg = new Point2d(difEndSegmentArc_x, difEndSegmentArc_x);
sampleSegment = arcSegment2dAt.GetSamplePoints(11)[5];
double difMidSegmentArc_x = (sampleSegment.X - gridPadding) - x;
double difMidSegmentArc_y = (sampleSegment.Y - y) / profileViewStyle.GraphStyle.VerticalExaggeration + profileView.ElevationMin;
coodSampleSegment = new Point2d(difMidSegmentArc_x, difMidSegmentArc_y);
profile.Entities.AddFixedSymmetricParabolaByThreePoints(coodStartSeg, coodSampleSegment, coodEndSeg);
break;
case SegmentType.Coincident:
break;
case SegmentType.Point:
break;
case SegmentType.Empty:
break;
default:
break;
}
}
}
- Create an empty 3D polyline.
Polyline3d polyline3D = new Polyline3d();
blockTableRecord.AppendEntity(polyline3D);
- Obtain the alignment associated with the profile view to extract the easting and northing coordinates.
ObjectId alignmentId = profileView.AlignmentId;
Alignment alignment = tx.GetObject(alignmentId, OpenMode.ForRead, false) as Alignment;
- Go through the PVIs (Points of Vertical Intersection) of the profile and Add the PVI coordinates and elevations to the 3D Polyline..
foreach (ProfilePVI profilePVI in profile.PVIs)
{
double offset = 0.0;
double northing = 0.0;
double easting = 0.0;
double station = profilePVI.RawStation;
double elevation = profilePVI.Elevation;
// Get the coordinates easting and northing from Alignment
alignment.PointLocation(station, offset, ref easting, ref northing);
// Add the profile entity vertices to the 3D polyline
Point3d point = new Point3d(easting, northing, elevation);
PolylineVertex3d point3dVertex = new PolylineVertex3d(point);
polyline3D.AppendVertex(point3dVertex);
}
- Add the 3D polyline to the model and Delete Profile.
// Add the 3D polyline to the model space
tx.AddNewlyCreatedDBObject(polyline3D, true);
// Remove profile
profile.Erase();
- Download the binary Compiled and tested with the Civil 3D 2024 version. Here
- If you load with the command
NETLOAD
Remember to unblock the .dll in the right-click properties window before! If you unblock the .dll afterNETLOAD
, you must restart C3D.
In the next posts, I will show how to compile this code and how to create an Interface on Civil 3D.
References: