PROFILE FROM POLYLINE

cpusey
Contributor
Contributor

PROFILE FROM POLYLINE

cpusey
Contributor
Contributor
I have a bunch of profiles with the finished grade shown with a polyline. I have to generate roadway corridors from these profiles (done by others) I am able to put there polylines in my profiles correctly and would like to convert the polyline to the finish grade proflie without having to click on every vertex. Can this be done?
Reply
Accepted solutions (1)
34,010 Views
49 Replies
Replies (49)

kh_night
Enthusiast
Enthusiast

There problem when polyline is reverse! First vertex of polyline must be at the first of Profile View.

0 Likes

MGO-Norsyn
Advocate
Advocate

Hi

The program expects a Polyline Class from selection:

promptEntityOptions1.AddAllowedClass(typeof(Polyline), true);

The class is described here: https://help.autodesk.com/view/OARX/2020/ENU/?guid=OARX-ManagedRefGuide-Autodesk_AutoCAD_DatabaseSer...

 

So the object must be a so called "Lightweight Polyline", else it will reject the input with the error message: "Not a polyline".

 

The properties pallette  must display: "Polyline". If it displays "2D Polyline", the object is a "Heavy" polyline and will be rejected.

 

MichaelButzen
Contributor
Contributor

When I convert a polyline to profile. The profile is shifted to the right. Did anybody experience this problem?

0 Likes

MGO-Norsyn
Advocate
Advocate

Hi

Sorry, no, I have not experienced the same problem -- my profiles are created as drawn.

0 Likes

kh_night
Enthusiast
Enthusiast

It happens when your profile view first station isn't zero!! The program(DLL) has to update.😁

0 Likes

david.silva
Contributor
Contributor

Although the program works and the results look attractive, I have some comments on the algorithm and on the code implementation:

 

First why would you want to have arcs on a polyline that you want to convert to a profile, unless, of course, the profile view style has no vertical exaggeration and, if that is the case then the code should be inserting circular vertical curves instead of symmetrical parabolas. Even in this case you need to check for proper tangency conditions between the vertical curve and the tangents.

If, despite all these reasons, you still want to convert arcs to a profile, then you would need to sample enough points along the arc to draw tangents between them. The number of sampling points varies, depending on the arc’s radius and the precision you want.

 

Regarding the code implementation, I can’t see the need to sample 10 or 11 points along the circular arcs if in the end you are only using the mid point to insert a fixed symmetrical parabola!! Again, no tangency checks are made between the tangents and the vertical curve.

 

In my program, I do not allow the polyline to have any arcs (just check the polyline’s property “HasBulges”).

After you have inserted all the tangents, inserting curves is trivial, just choose the PVI you want and insert a floating vertical curve (circular, parabola…) between the tangents that share that PVI.

 

Also, you can determine the profile view’s vertical exaggeration and horizontal orientation without getting its style: just determine profile view’s min and max station and elevation and then get its WCS coordinates of those 2 points (the 2 corners of the profile view: Lower left and Top Right) and the vertical exaggeration is the ratio between  the DeltaY and the DeltaElevation. If DeltaX is negative, the profile view is oriented from right to left.

kh_night
Enthusiast
Enthusiast

Here is my code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.GraphicsSystem;
using Autodesk.AutoCAD.Geometry;

using Autodesk.Civil.ApplicationServices;
using Autodesk.Civil.DatabaseServices;
using Autodesk.Civil.DatabaseServices.Styles;

namespace ProfileToolBox
{
    public class Profiles
    {
        [CommandMethod("pfp")]
        public void profilefrompolyline()
        {
            Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
            CivilDocument civildoc = CivilApplication.ActiveDocument;
            Database db = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Database;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                try
                {
                    //----------------------------------------
                    PromptEntityOptions peo = new PromptEntityOptions("\n Select a polyline : ");
                    peo.SetRejectMessage("\n Not a polyline");
                    peo.AddAllowedClass(typeof(Autodesk.AutoCAD.DatabaseServices.Polyline), true);
                    PromptEntityResult per = ed.GetEntity(peo);
                    if (per.Status != PromptStatus.OK) return;
                    ObjectId plineId = per.ObjectId;
                    //-----------------------------------------
                    PromptEntityOptions peo2 = new PromptEntityOptions("\n Select a ProfileView: ");
                    peo.SetRejectMessage("\n Not a ProfileView");
                    peo.AddAllowedClass(typeof(ProfileView), true);
                    PromptEntityResult per2 = ed.GetEntity(peo2);
                    if (per2.Status != PromptStatus.OK) return;
                    ProfileView pv = trans.GetObject(per2.ObjectId, OpenMode.ForWrite) as ProfileView;
                    double x0 = 0;
                    double y0 = 0;
                    double Sta0 = pv.StationStart;
                    if (pv.ElevationRangeMode == ElevationRangeType.Automatic)
                    {
                        pv.ElevationRangeMode = ElevationRangeType.UserSpecified;
                        pv.FindXYAtStationAndElevation(pv.StationStart, pv.ElevationMin, ref x0, ref y0);
                    }
                    else
                    {
                        pv.FindXYAtStationAndElevation(pv.StationStart, pv.ElevationMin, ref x0, ref y0);
                    }
                    Autodesk.Civil.DatabaseServices.Styles.ProfileViewStyle PVstyle = trans.GetObject(pv.StyleId, OpenMode.ForRead) as Autodesk.Civil.DatabaseServices.Styles.ProfileViewStyle;

                    //-------------------------------------
                    Alignment oAlignment = trans.GetObject(pv.AlignmentId, OpenMode.ForRead) as Alignment;
                    ObjectId layerId = oAlignment.LayerId;
                    ObjectId styleId = civildoc.Styles.ProfileStyles[0];

                    ObjectId labelSetId = civildoc.Styles.LabelSetStyles.ProfileLabelSetStyles[0];
                    ObjectId oProfileId = Profile.CreateByLayout(oAlignment.Name + "-" + DateTime.Now.ToShortTimeString(), pv.AlignmentId, layerId, styleId, labelSetId);
                    Profile oProfile = trans.GetObject(oProfileId, OpenMode.ForWrite) as Profile;
                    //-----------------------------------------------------------
                    BlockTableRecord btr = trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
                    Autodesk.AutoCAD.DatabaseServices.Polyline pline = trans.GetObject(plineId, OpenMode.ForRead, false) as Autodesk.AutoCAD.DatabaseServices.Polyline;
                    if (pline != null)
                    {
                        int segCount = pline.NumberOfVertices - 1;
                        double xs = 0;
                        double ys = 0;
                        double xe = 0;
                        double ye = 0;
                        for (int cnt = 0; cnt < segCount; cnt++)
                        {
                            SegmentType type = pline.GetSegmentType(cnt);
                            switch (type)
                            {
                                case SegmentType.Line:
                                    {
                                        LineSegment2d Liseg2d = pline.GetLineSegment2dAt(cnt);
                                        xs = Liseg2d.StartPoint.X;
                                        ys = Liseg2d.StartPoint.Y;
                                        double sta = xs - x0 + Sta0;
                                        double dh = (ys - y0) / (PVstyle.GraphStyle.VerticalExaggeration) + pv.ElevationMin;
                                        Point2d startpo = new Point2d(sta, dh);
                                        xe = Liseg2d.EndPoint.X;
                                        ye = Liseg2d.EndPoint.Y;
                                        double sta2 = xe - x0 +Sta0;
                                        double dh2 = (ye - y0) / (PVstyle.GraphStyle.VerticalExaggeration) + pv.ElevationMin;
                                        Point2d endpo = new Point2d(sta2, dh2);
                                        ProfileTangent oTangent1 = oProfile.Entities.AddFixedTangent(startpo, endpo);
                                        break;
                                    }
                                case SegmentType.Arc:
                                    {
                                        CircularArc2d arcseg = pline.GetArcSegment2dAt(cnt);
                                        xs = arcseg.StartPoint.X;
                                        ys = arcseg.StartPoint.Y;
                                        xe = arcseg.EndPoint.X;
                                        ye = arcseg.EndPoint.Y;
                                        double sta = xs - x0 + Sta0;
                                        double dh = (ys - y0) / (PVstyle.GraphStyle.VerticalExaggeration) + pv.ElevationMin;
                                        double sta2 = xe - x0 + Sta0;
                                        double dh2 = (ye - y0) / (PVstyle.GraphStyle.VerticalExaggeration) + pv.ElevationMin;
                                        Point2d po = arcseg.GetSamplePoints(11)[5];
                                        double sta3 = po.X - x0 + Sta0;
                                        double dh3 = (po.Y - y0) / (PVstyle.GraphStyle.VerticalExaggeration) + pv.ElevationMin;
                                        Point2d meanpo = new Point2d(sta3, dh3);
                                        Point2d endpo = new Point2d(sta2, dh2);
                                        Point2d startpo = new Point2d(sta, dh);
                                        ProfileParabolaSymmetric oCurve = oProfile.Entities.AddFixedSymmetricParabolaByThreePoints(startpo, meanpo, endpo);
                                        break;
                                    }
                            }
                        }
                    }

                }
                catch (System.Exception ex)
                {
                    ed.WriteMessage("\n" + ex.Message);
                }
                trans.Commit();
            }

        }
    }
}

 

you can edit or customize it or add AI to find the best fit and optimize your profile.

MGO-Norsyn
Advocate
Advocate

I would like to comment that the original code perfectly fits my needs. I use profiles to visualize district heating pipe longitudinal profiles. Piping profiles need to have arcs when elevation changes moderately and thus I draw I my profiles using polylines and the convert, using the program present here, to profiles.

 

Arc is a special case of a symmetrical parabola and supplying start, end and midpoint is enough to define the arc (parabola) segment. I, of course, check for tangency when creating the polyline.

 

Everybody uses the software differently and I am sure that your use case is perfectly useful for you, while mine is for me.

 
* Edited by Discussion Admin

 

0 Likes

david.silva
Contributor
Contributor

I am sorry if my post was in anyway perceived a negative critic. It was not my intention.

 

In fact, it was quite the opposite: I looked at the code and a few aspects did not feel right to me and I decided I should address them.

 

Nonetheless, all the aspects I mentioned are not checked by the code shared in this topic.

 

@Anonymous : That answers my question about why would you want to have arcs on a profile. However, I cannot see what geometric figure would deform (caused by the profile view’s vertical exaggeration) to a perfect arc. Unless of course you use it with a profile view’s that has no vertical exaggeration. Please correct me if I am wrong.

 

My purpose in this forum is to learn and to share knowledge. I may suggest and disagree but I never criticize the work of others, especially code, as I am a self-taught VB man and far from being an expert.

0 Likes

MGO-Norsyn
Advocate
Advocate

I draw profiles by using polylines in undeformed views. When publishing drawings, I change the profile view style to one with vertical exaggeration. 

0 Likes

dilsmails
Advocate
Advocate

Hi,

Before It was working perfectly for me. now it creates the profiles but curves are not updating related to tangents.  in the Screen shot,  above profile is created just now (C3d 2020) and bellow is created almost 1 year ago ( don't remember which version)

problems are :

1. vertical curve is created in some locations but not all the curve locations.

2. tangent line is not appearing even all layer is on.

3. curve is not related to tangents, (means, it will not update the tangents when ew made changes in the curve.

4. the circular grip is not in the mid of the curve. ( i have shown that by dragging the curve for better understanding ) 

Can you please help me to resolve the problem?

 

 

a.png

Dileep
0 Likes

dilsmails
Advocate
Advocate

this also not working for me now. i don't know what happened. before i worked with this perfectly 

Dileep
0 Likes

MGO-Norsyn
Advocate
Advocate

Hi

If you're referring to the version I published on my Github, then it was compiled for C3D 2019. You could try compiling it for the version you are working on to see if it changes anything.

dilsmails
Advocate
Advocate

Thanks for your reply. any way i don't have knowledge of editing that program. If your time permits  can you please update it to compactable with C3D 2020 and above versions 

or anyone can do this please help.

 

Thanks in advance.

DK

Dileep
0 Likes

MGO-Norsyn
Advocate
Advocate
You don't have to edit anything. You just have to open the solution, which you can download from GitHub, in Visual Studio Community Edition and then, in the solution explorer, under 'References' header, update location of Autocad specific references. You can see that they are Autocad specific if they refer to a file in Autocad installation directory. You can see the path when you select the reference and it appears in properties window.
0 Likes

dilsmails
Advocate
Advocate

With earlier versions of civil 3D this program was working perfectly for me. Now I am working in C3D 2020. 2020 In this version it creates the profile, but vertical curves are not dynamically connected to the both tangents. If you can resolve and update the program it will be highly apricated.

Thanks

Dileep
0 Likes

knuwan
Enthusiast
Enthusiast

Is it possible to Insert new PVI points to the profile created using your method? I tried but it did not allow me. do you have a fix for it? some of the PVI elevations editable but most of them are not! Thanks! (I use Civil 2021)

0 Likes

MGO-Norsyn
Advocate
Advocate
I am sorry I don't know. But couldn't you just edit the original polyline and then make a new profile?
0 Likes

kh_night
Enthusiast
Enthusiast
I think, this profile may be static!? Select this profile and right click and select properties and then in properties dialogue, check profile update mode. It would be static and if it was Dynamic change to Static.
0 Likes

kh_night
Enthusiast
Enthusiast
Ok. Just send your dwg file to me. I'll try to solve any issues if I can.
0 Likes