Published on

1 - Project Polyline From Profile View

Authors
  • avatar
    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.

Project Polyline

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:

  1. Select a polyline.
  2. Select a profile view.
  3. Create an empty profile.
  4. Extract the geometry information from the Polyline and add it to the empty Profile.
  5. Create an empty 3D polyline.
  6. Obtain the alignment associated with the profile view to extract the easting and northing coordinates.
  7. Go through the PVIs (Points of Vertical Intersection) of the profile.
  8. Add the PVI coordinates and elevations to the 3D Polyline.
  9. Add the 3D polyline to the model and Delete Profile.

Below, I will explain each step with the accompanying code.

  1. 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;
  1. 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;
  1. 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;
  1. 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;
        }
    }

}
  1. Create an empty 3D polyline.
Polyline3d polyline3D = new Polyline3d();
blockTableRecord.AppendEntity(polyline3D);
  1. 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;
  1. 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);
    
}
  1. 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 after NETLOAD, 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: