Civil3D API c# extract label text

Civil3D API c# extract label text

Anonymous
Not applicable
4,405 Views
10 Replies
Message 1 of 11

Civil3D API c# extract label text

Anonymous
Not applicable

 

I want to extract the text in the label,

 

Its a civil 3D label (example pipe, structure, etc)

I am able to get the style name and the text. But the issue is text which i get using he current code is all text so I am not able to get component wise text.

 

Check the attached screen grab,

 My label contains three components,

KN, Top and Bot, I want to extract the text within each of those component. 

 

Is there a way to get that?

 

My Code as follows,

public static class LabelTextExtractor
    {
        public static string GetDisplayedLabelText(ObjectId labelId)
        {
            //if (labelId.ObjectClass.DxfName.ToUpper() != "AECC_GENERAL_SEGMENT_LABEL")
            //{
            //    throw new ArgumentException(
            //        "argument mismatch: not an \"AECC_GENERAL_SEGMENT_LABEL\"");
            //}

            StringBuilder lblText = new StringBuilder();

            using (var tran = labelId.Database.TransactionManager.StartTransaction())
            {
                var label = tran.GetObject(labelId, OpenMode.ForRead) as CivilDb.Label;
                if (label != null)
                {
                    bool changed = !label.Dragged && label.AllowsDragging;
                    try
                    {
                        if (changed)
                        {
                            label.UpgradeOpen();
                            double delta = label.StartPoint.DistanceTo(label.EndPoint);
                            label.LabelLocation =
                                new Point3d(label.LabelLocation.X +
                                    delta, label.LabelLocation.Y +
                                    delta, label.LabelLocation.Z);
                        }

                        var dbObjs = FullExplode(label);
                        foreach (var obj in dbObjs)
                        {
                            if (obj.GetType() == typeof(DBText))
                            {
                                lblText.Append(" " + (obj as DBText).TextString);
                            }

                            obj.Dispose();
                        }
                    }
                    finally
                    {
                        if (changed) label.ResetLocation();
                    }
                }

                tran.Commit();
            }

            return lblText.ToString().Trim();
        }

        #region private methods

        private static List<CadDb.DBObject> FullExplode(CadDb.Entity ent)
        {
            // final result
            List<CadDb.DBObject> fullList = new List<CadDb.DBObject>();

            // explode the entity
            DBObjectCollection explodedObjects = new DBObjectCollection();
            ent.Explode(explodedObjects);
            foreach (CadDb.Entity explodedObj in explodedObjects)
            {
                // if the exploded entity is a blockref or mtext
                // then explode again
                if (explodedObj.GetType() == typeof(CadDb.BlockReference) ||
                    explodedObj.GetType() == typeof(CadDb.MText))
                {
                    fullList.AddRange(FullExplode(explodedObj));
                }
                else
                    fullList.Add(explodedObj);
            }
            return fullList;
        }

        #endregion
    }
0 Likes
4,406 Views
10 Replies
Replies (10)
Message 2 of 11

brianchapmandesign
Collaborator
Collaborator

Haven't time to test the code but looks like going the right route. Basically have to explode them through the code, search the strings for "top, bot, etc" and store / use them however you like.


"Very funny, Scotty. Now beam down my clothes.
0 Likes
Message 3 of 11

hippe013
Advisor
Advisor

I was able to extract the component text by going through the label style. The following example prints to the command line the label's text component name and contents. Is this what you are looking to do?

 

VB.net

<CommandMethod("GetLabelComponents")> _
        Public Sub GetComp()
            Dim aDoc As Document = Application.DocumentManager.MdiActiveDocument
            Dim ed As Editor = aDoc.Editor
            Dim db As Database = aDoc.Database
            Dim opts As New PromptEntityOptions(vbCrLf + "Select Label")
            opts.SetRejectMessage(vbCrLf + "Must be a Label")
            opts.AddAllowedClass(GetType(GeneralSegmentLabel), True)
            Dim res As PromptEntityResult = ed.GetEntity(opts)
            If res.Status = PromptStatus.OK Then
                Using trans As Transaction = db.TransactionManager.StartTransaction
                    Dim Lbl As GeneralSegmentLabel
                    Lbl = trans.GetObject(res.ObjectId, OpenMode.ForRead)
                    Dim LblStlId As ObjectId = Lbl.StyleId
                    Dim lblStl As Styles.LabelStyle
                    lblStl = trans.GetObject(LblStlId, OpenMode.ForRead)
                    Dim comps As New ObjectIdCollection
                    comps = lblStl.GetComponents(Styles.LabelStyleComponentType.Text)
                    For Each id As ObjectId In comps
                        Dim comp As Styles.LabelStyleTextComponent = trans.GetObject(id, OpenMode.ForRead)
                        ed.WriteMessage(vbCrLf + comp.Name)
                        ed.WriteMessage(vbCrLf + comp.Text.Contents.Value)
                    Next
                    trans.Commit()
                End Using
            End If
        End Sub
0 Likes
Message 4 of 11

Jeff_M
Consultant
Consultant

@hippe013, the OP is looking to get the displayed contents of the label, not what the style defines. In the case of a distance label, it would return "123.54" not "<[General Overall Length(Uft|P2|RN|AP|Sn|OF)]>".

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

hippe013
Advisor
Advisor

Thank you for the clarification Jeff. So, as it appears, the resulting text of the component string isn't exposed or implemented in the GeneralSegmentLabel Class.(?) That would be the reason they are exploding the object to get to the resulting text? I'll keep digging on my end.

0 Likes
Message 6 of 11

Jeff_M
Consultant
Consultant
Yes, hippe013, the values of the label are not exposed. You can use the GetTextComponentOverride() method which will return any added text. But any of the built in properties that return the values are still returned as the property formula and not the actual text.
Jeff_M, also a frequent Swamper
EESignature
0 Likes
Message 7 of 11

Anonymous
Not applicable

Thanks Guys,

 

 I am able to do it,

 

1. First I get the Draworder of the components,

2. Get the object type of each of those components

3. When I tried to explode individual components I add them to an array in the right order .

 

Note:

There are three types of text - Text component, Text for each component and another one is Reference text. 

Also some of these components may have multi-line text so when you exploded it, you need to concat that string or make sure to add them as single object.

 

 

0 Likes
Message 8 of 11

David_Prontnicki
Collaborator
Collaborator

Jeff,

So when you say the values of the labels are not exposed, does that mean you also cant override the text for a label? I have a post already asking; but I saw your reply here. If I have a surface label can I override the text for each component? Example, say I have a surface elevation label that has two text components, TC and BC. Can select that label and override the values that are there? If so, do you know how to do that. I would think it's possible because there is a command in Civil 3D to do just that. I can right click on a label and select Edit Label Text. Is this accessible through the API?

 

Thank you!

0 Likes
Message 9 of 11

Jeff_M
Consultant
Consultant

Yes, @David_Prontnicki. I just replied to your other post.

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

granat1
Contributor
Contributor

very thanck for you code 

without this i was anable to continue

 

0 Likes
Message 11 of 11

granat1
Contributor
Contributor

SPOT SURFACE LEVEL

CAN I CHANGE A TEXT COMPOSANTTO REFERENCE TO AN AUTHER SURFACE ?

WHERE IS WRITE THE REFERENCE SURFACE NAME?

I HAVE A LABEL THAT SHOW THE LEVEL OF A SECOND SURFACE BY REFERENCE TEXT

CAN I ALSO CHANGE HIM ? WHERE IS HE IN THE DATA BASE ? NOT ONLY THE NAME OR THE  FORMAT 

TANCK YOU

0 Likes