Use C#.NET to get an existing profile view style by it name

Use C#.NET to get an existing profile view style by it name

hencoop
Advisor Advisor
4,913 Views
10 Replies
Message 1 of 11

Use C#.NET to get an existing profile view style by it name

hencoop
Advisor
Advisor

Hello all,

I'm still a Noob with C#.NET

I hacked @_gile's dump routine to set a UCS to match a selected Profile View object; however, I am only able to extract the name of the Profile View Style and not the style itself.  I would like to get the style.VerticalScale and style.VerticalExaggeration from the style whose name I have.  How do I get access to these ProfileViewXStyle properties if I'm starting with just its name?

 

I have existing Lisp routines that require a couple of user inputs to set the UCS.  My use has my UCS Y-values equal (Elevation * Exaggeration) and X-values equal Station.  The only thing I'm missing is verifying the Profile View's Vertical Scale and/or Exaggeration.

 

Thanks!

Henry C. Francis
Authorized Autodesk Developer
Civil Design Specialist – Water & Wastewater Infrastructure
0 Likes
Accepted solutions (1)
4,914 Views
10 Replies
Replies (10)
Message 2 of 11

Jeff_M
Consultant
Consultant

Since you already have the ProfileView object, just do this:

 

var pvstyle = (ProfielViewStyle)tr.GetObject(pvObj.StyleId, OpenMode.ForRead);
Jeff_M, also a frequent Swamper
EESignature
0 Likes
Message 3 of 11

hencoop
Advisor
Advisor

@Jeff_M  I don’t think I actually exposed that object.  Because of how the dump code works I only have a ReflectedType, Type and Value.  I suspect there is a better and more direct method but Dump worked to show me the “stuff” of a ProfileView.  if I had the objects themselves I could not figure out how to access them.  I was able to capture the values that were exposed by Dump but the only value I’ could capture for the ProfileViewStyle was its Name.  I need another lesson that explains syntax and structure for C#.NET.  The course I took showed me how to do lots of specific things but was pretty light on why.  If it wasn’t for Visual Studio being very helpful in identifying and fixing many structural errors I would be foundering even more than I am.

 

 

Henry C. Francis
Authorized Autodesk Developer
Civil Design Specialist – Water & Wastewater Infrastructure
0 Likes
Message 4 of 11

Jeff_M
Consultant
Consultant

If you want to see the 'stuff' of a C3D object, just have a look at the C3D .NET API help:

http://help.autodesk.com/view/CIV3D/2021/ENU/?guid=d5bc920a-7c8c-92fb-fa84-bcc1c8757845

 

Also, the Intellisense in Visual Studio should help a great deal.

 

You said "match a selected Profile View object" which tells me you have the PV object. The code I showed will work to get what you need. You could share your code to get some better input...

 

 

Jeff_M, also a frequent Swamper
EESignature
0 Likes
Message 5 of 11

hencoop
Advisor
Advisor

Thanks @Jeff_M 

Here's the code.  I made a several attempts to get at the object properties.  I could not even manipulate the Location Point3d object.  I could turn it into a string and use that so that's what I did.  My latest effort to get at the ProfileViewStyle is to assign it to pvStyObj.  I commented that code out because it threw an exception I couldn't solve.  The @_gile code steps through everything but I just cannot figure out how to code getting at the properties of the ProfileViewStyle as it passes by.

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.Civil.DatabaseServices.Styles;
using System;
using System.Collections.Generic;
using System.Reflection;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

[assembly: CommandClass(typeof(DumpEntityProperties.Commands))]

namespace DumpEntityProperties
{
    public class Commands
    {
        private bool doDump;

        [CommandMethod("PvUCS")]
        public void SetUCS()
        {
            Document doc = AcAp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            doDump = false;
            var entRes = ed.GetEntity("\nSelect Profile View: ");
            if (entRes.Status == PromptStatus.OK)
            {
                PrintDump(entRes.ObjectId, ed);
            }
        }

        [CommandMethod("Dump")]
        //Hacked from user _gile https://forums.autodesk.com/t5/net/how-to-find-the-displayed-properties-value-of-selected-object/td-p/7083701
        public void Dump()
        {
            Document doc = AcAp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            doDump = true;
            var entRes = ed.GetEntity("\nSelect object: ");
            if (entRes.Status == PromptStatus.OK)
            {
                PrintDump(entRes.ObjectId, ed);
                AcAp.DisplayTextScreen = true;
            }
        }

        private void PrintDump(ObjectId id, Editor ed)
        {
            var flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.GetProperty;

            using (var tr = id.Database.TransactionManager.StartTransaction())
            {
                var dbObj = tr.GetObject(id, OpenMode.ForRead);
                var types = new List<Type>();
                var profLocn = new Object();
                var startSta = new Object();
                var minElev = new Object();
                var profStyl = new Object();
                Object pvStyObj = new Object();
                double vScale = 1;
                double vExag = 1;

                types.Add(dbObj.GetType());
                while (true)
                {
                    var type = types[0].BaseType;
                    types.Insert(0, type);
                    if (type == typeof(RXObject))
                    {
                        break;
                    }
                    else if (type == typeof(ProfileViewStyle))
                    {
                        pvStyObj = type;
                    }
                }
                foreach (Type t in types)
                {
                    foreach (var prop in t.GetProperties(flags))
                    {
                        try
                        {
                            if (t.Name == "Entity" && prop.Name.ToString() == "StyleName")
                            {
                                //ed.WriteMessage("\nBegin Store Style Name! ");
                                //ProfileViewStyle style = pvStyObj as ProfileViewStyle;
                                //GraphStyle grStyl = style.GraphStyle;
                                //vScale = grStyl.VerticalScale;
                                //vExag = grStyl.VerticalExaggeration;
                                profStyl = prop.GetValue(dbObj, null).ToString();
                                //ed.WriteMessage("\nVertical Scale: " + vScale.ToString());
                                //ed.WriteMessage("\nVertical Exaggeration: " + vExag.ToString());
                                //ed.WriteMessage("\nEnd Store Style Name! ");
                            }
                            if (t.Name == "Graph" && prop.Name.ToString() == "Location")
                            {
                                profLocn = prop.GetValue(dbObj, null);
                            }
                            if (t.Name == "ProfileView" && prop.Name.ToString() == "StationStart")
                            {
                                startSta = prop.GetValue(dbObj, null);
                            }
                            if (t.Name == "ProfileView" && prop.Name.ToString() == "ElevationMin")
                            {
                                minElev = prop.GetValue(dbObj, null);
                            }
                            if (doDump != false)
                            {
                                ed.WriteMessage("\nReflected Type: {0}\n\t\tType: {1}\n\t\tValue: {2}", prop.ReflectedType.Name, prop.PropertyType.Name, prop.GetValue(dbObj, null));
                                ed.WriteMessage("\n\t\tprop Name: {0}\n\t\tprop Attributes: {1}", prop.Name, prop.Attributes.ToString());
                                ed.WriteMessage("\n\t\tCalling Convention: {0}", prop.GetMethod.CallingConvention.ToString());
                                ed.WriteMessage("\n\t\tMethod Implementation Flags: {0}", prop.GetMethod.MethodImplementationFlags.ToString());
                                ed.WriteMessage("\n\t\tReturn Parameter: {0}", prop.GetMethod.ReturnParameter.ToString());
                                ed.WriteMessage("\n\t\tReturn Type: {0}", prop.GetMethod.ReturnType.ToString());
                                ed.WriteMessage("\n\t\tAttributes: {0}\n", prop.GetMethod.Attributes.ToString(), prop.IsSpecialName.ToString());
                            }
                        }
                        catch (System.Exception e)
                        {
                            ed.WriteMessage("\n" + e.Message);
                        }
                    }
                }

                if (doDump == false)
                {
                    try
                    {
                        string yoffSet = minElev.ToString();
                        string origPtx = profLocn.ToString();
                        string xoffSet = startSta.ToString();
                        var ThisDrawing = Application.DocumentManager.MdiActiveDocument;
                        string origPt = origPtx;
                        origPtx = origPtx.Replace("(", "(TRANS(LIST ").Replace(",", " ").Replace(")", ")0 1)");
                        ed.WriteMessage("\norigPt: {0}\norigPtx: {1}\nX-offset: {2}\nY-offset: {3}\nProfile Style: {4}\nVert. Scale: {5}\nVert.Exaggeration: {6}", origPt, origPtx, xoffSet, yoffSet, profStyl, vScale.ToString(), vExag.ToString());
                        ThisDrawing.SendStringToExecute("._ucs non", true, false, false);
                        ThisDrawing.SendStringToExecute(" (POLAR(POLAR" + origPtx + "(* PI 1.5)" + yoffSet + ")PI " + xoffSet + ")", true, false, false);
                        ThisDrawing.SendStringToExecute(" non @100<0", true, false, false);
                        ThisDrawing.SendStringToExecute(" non @100<90 ", true, false, false);
                    }
                    catch (System.Exception ex)
                    {
                        ed.WriteMessage("\n" + ex.Message);
                    }
                }
                tr.Commit();
            }
        }
    }
}

  

Henry C. Francis
Authorized Autodesk Developer
Civil Design Specialist – Water & Wastewater Infrastructure
0 Likes
Message 6 of 11

hencoop
Advisor
Advisor

@Jeff_M I finally found out how to get at the ProfileViewStyles collection.  With this I think I can compare the name I have with each item in the collection to find the VerticalScale and VerticalExaggeration of my target style.

 

        [CommandMethod("ListProfileViewStyles")]
        public void ListPipeNetworks()
        {
            // Get all the Profile View Styles
            CivilDocument doc = CivilApplication.ActiveDocument;
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            using (Transaction ts = Application.DocumentManager.MdiActiveDocument.Database.TransactionManager.StartTransaction())
            {
                for (int i = 0; i < doc.Styles.ProfileViewStyles.Count; i++)
                {

                    ObjectId profileViewStyleId = doc.Styles.ProfileViewStyles[i];
                    ProfileViewStyle oProfileViewStyle = ts.GetObject(profileViewStyleId, OpenMode.ForRead) as ProfileViewStyle;

                    ed.WriteMessage("\nProfile View Style Name: {0}", oProfileViewStyle.Name);
                }

                ts.Commit();
            }
        }

 

 

Henry C. Francis
Authorized Autodesk Developer
Civil Design Specialist – Water & Wastewater Infrastructure
0 Likes
Message 7 of 11

Jeff_M
Consultant
Consultant
@hencoop, ditch the dump code. Use it for informational purposes only. I think it's confusing you more than helping... When I use the Dump tool from gile, I'm getting this for a ProfileView:
StyleId : Property Get method was not found.
StyleName : Property Get method was not found.

Give me a bit to get you an example of a better way to tackle what you are trying to do.
Jeff_M, also a frequent Swamper
EESignature
0 Likes
Message 8 of 11

hencoop
Advisor
Advisor

@Jeff_M  Like I said, I'm still very much a Noob with C#.NET and there's probably a better more direct way to do what I need... but my code hack is setting the UCS without error for me thus far.  I started out with dump hoping to get some insight into the "stuff" like I would with (VLAX-DUMP-OBJECT ...).  It did help me see some things but it severely limited my access to the actual objects underlying it all.   So, refusing to be denied, I just used the text I COULD get and passed it to a lisp expression at the command line... voila!  I got the result I wanted (sans the VerticalScale or VerticalExaggeration).

Henry C. Francis
Authorized Autodesk Developer
Civil Design Specialist – Water & Wastewater Infrastructure
0 Likes
Message 9 of 11

hencoop
Advisor
Advisor

@Jeff_M Here are the results on my system:

Command: NETLOAD

Command: PVUCS

Select Profile View:
origPt: (1733228.80990624,917571.194444939,0)
origPtx: (TRANS(LIST 1733228.80990624 917571.194444939 0)0 1)
X-offset: 950
Y-offset: 850
Profile Style: LKC Roadway Grid
Vert. Scale: 1
Vert.Exaggeration: 1
Command:
Current ucs name:  *WORLD*
Specify origin of UCS or [Face/NAmed/OBject/Previous/View/World/X/Y/Z/ZAxis] <World>:   (1.73228e+06 916721.0 0.0)

Specify point on X-axis or <accept>:
Specify point on the XY plane or <accept>:

The Vert. Scale and Exaggeration are declared as double vScale = 1; and, double vExag = 1; respectively and I am unable to reset their values before they are written out so far.

The practical result is that I have set the UCS I want (as long as the Vertical Exaggeration = 10)

Henry C. Francis
Authorized Autodesk Developer
Civil Design Specialist – Water & Wastewater Infrastructure
0 Likes
Message 10 of 11

Jeff_M
Consultant
Consultant
Accepted solution

I don't typically use UCS's so not exactly sure how you are using the vertical exaggeration. This code should help you get closer to a final result.

 

        [CommandMethod("PvUCS")]
        public void SetUCS()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            var entOpts = new PromptEntityOptions("\nSelect Profile View: ");
            entOpts.SetRejectMessage("...not  aProfileView, try again.");
            entOpts.AddAllowedClass(typeof(ProfileView), true);
            var entRes = ed.GetEntity(entOpts);
            if (entRes.Status != PromptStatus.OK)
                return;
            using (var tr = db.TransactionManager.StartTransaction())
            {
                var pvObj = (ProfileView)tr.GetObject(entRes.ObjectId, OpenMode.ForRead);
                var pvStyle = (ProfileViewStyle)tr.GetObject(pvObj.StyleId, OpenMode.ForRead);
                var profLocn = pvObj.Location;
                var startSta = pvObj.StationStart;
                var minElev = pvObj.ElevationMin;
                double vScale = pvStyle.GraphStyle.VerticalScale;
                double vExag = pvStyle.GraphStyle.VerticalExaggeration;
                var ucsOrigin = profLocn.GetPolarPoint(Math.PI, startSta);
                ucsOrigin = ucsOrigin.GetPolarPoint((Math.PI * 1.5), minElev);
                ed.CurrentUserCoordinateSystem = Matrix3d.AlignCoordinateSystem(
                Point3d.Origin, Vector3d.XAxis, Vector3d.YAxis, Vector3d.ZAxis,
                ucsOrigin, Vector3d.XAxis, Vector3d.YAxis, Vector3d.ZAxis);
                tr.Commit();
            }
        }
        /// <summary>
        /// Point3d Extension method
        /// Calculates a new point on the same plane, using the specified angle and distance.  Angle should be specified
        /// counter-clockwise from the X-axis.
        /// </summary>
        public static Point3d GetPolarPoint(this Point3d ptBase, double angle, double distance)
        {
            return new Point3d(ptBase.X + (distance * Math.Cos(angle)), ptBase.Y + (distance * Math.Sin(angle)), ptBase.Z);
        }
Jeff_M, also a frequent Swamper
EESignature
Message 11 of 11

hencoop
Advisor
Advisor

@Jeff_M Thank you for taking the time to write the code.  I was certain there was a much better way to do this.

 

I added/modified the following to give me some feedback:

 

 

 

                string pvName = pvObj.Name;
                string pvsName = pvStyle.Name;
                double hScale = pvStyle.GraphStyle.CurrentHorizontalScale;
                double vScale = pvStyle.GraphStyle.VerticalScale;
                double vExag = pvStyle.GraphStyle.VerticalExaggeration;
                var ucsOrigin = profLocn.GetPolarPoint(Math.PI, startSta);
                ucsOrigin = ucsOrigin.GetPolarPoint((Math.PI * 1.5), minElev * vExag);
                ed.WriteMessage("\nProfile View: {0}\nProfile View Style: {1}\n\tHorizontal Scale: {2}\n\tVertical Scale: {3}\n\tVertical Exaggeration {4}", pvName, pvsName, hScale.ToString(), vScale.ToString(), vExag.ToString());

 

 

 

 

I have an app that does all of our pipeline Design and the Plan & Profile drafting of it.  I could not upload an image of its main dialog interface so I put it here: (GPDGN)   It either draws to the world coordinate system or to the coordinate system of a Profile View.  We use profile grid blocks with station and elevation attributes in Paper Space on sheets.  Another lisp routine sets the attribute values and the viewport position to match the grid.

 

Currently when drawing the profile on a C3D Profile View the user must select it and then provide the origin since neither it nor the "Location" property is exposed to Visual Lisp.  The Vertical Scale (COM) Vertical Exaggeration (NET) must be multiplied by the Minimum Elevation to set the origin of the coordinate system.  All of the design elevations are maintained and stored in real world values but they need to be exaggerated appropriately whenever the profile is drawn.   I only use the Civil 3D  existing and/or proposed grade profile objects.  They are read once from the Profile View and then stored independently (at actual elevations).  They'll get read again if my alignment changes but other than that I don't use the Profile View again. I will use all the C3D profile tools if I need to design a corridor but that isn't often.

Henry C. Francis
Authorized Autodesk Developer
Civil Design Specialist – Water & Wastewater Infrastructure
0 Likes