Solved! Go to Solution.
Solved by kh_night. Go to Solution.
There problem when polyline is reverse! First vertex of polyline must be at the first of Profile View.
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.
When I convert a polyline to profile. The profile is shifted to the right. Did anybody experience this problem?
Hi
Sorry, no, I have not experienced the same problem -- my profiles are created as drawn.
It happens when your profile view first station isn't zero!! The program(DLL) has to update.😁
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.
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.
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.
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.
I draw profiles by using polylines in undeformed views. When publishing drawings, I change the profile view style to one with vertical exaggeration.
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?
this also not working for me now. i don't know what happened. before i worked with this perfectly
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.
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
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
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)
Can't find what you're looking for? Ask the community or share your knowledge.