Civil3D.Net – Getting the Alignment Station Label Styles

This begins hopefully a long running series of how to use the .Net API for Civil 3D. The series will run as long as there are suggestions and ideas for what to write. For example, the exercise below is based upon Mike Robertson’s suggestion (hope I understood it right Mike).

All exercises will be based upon the assumption that you have read the Civil 3D .Net API 101 Series located here:

http://www.civil4d.com/2009/04/working-with-civil3d-2010-managed-net-api-101-1/

http://www.civil4d.com/2009/04/working-with-civil3d-2010-managed-net-api-101-2/

http://www.civil4d.com/2009/04/working-with-civil3d-2010-managed-net-api-101-3/

http://www.civil4d.com/2009/04/working-with-civil3d-2010-managed-net-api-101-4/

http://www.civil4d.com/2009/05/working-with-civil3d-2010-managed-net-api-101-5/

Ok to the exercise

Alignment Station Labels

When working in Civil 3D, you realize that alignment labels are split into labels that are applied to a specific point (i.e., Station Offset) and labels that are applied along a station range of the alignment (i.e. Station labels).

For our exercise, we want to get all the label style objects that are applied to the selected alignment. So let’s create a new command called GetAlignmentStationLabelStyles. So we create a class for this, add the imports that we will use (the key import for the command is the Autodesk.AutoCAD.Runtime Import). The class so far will look like this:

Imports System

Imports Autodesk.AutoCAD.Runtime

Imports Autodesk.AutoCAD.ApplicationServices

Imports Autodesk.AutoCAD.DatabaseServices

Imports Autodesk.AutoCAD.Geometry

Imports Autodesk.AutoCAD.EditorInput

 

<Assembly: ExtensionApplication(GetType(Commands))>

 

Public Class Commands

    Implements IExtensionApplication

 

    Public Sub Initialize() Implements IExtensionApplication.Initialize

        Autodesk.AutoCAD.ApplicationServices.Application. _

        DocumentManager.MdiActiveDocument.Editor.WriteMessage(vbLf & _

        "Loading " & My.Application.Info.AssemblyName)

    End Sub

 

    Public Sub Terminate() Implements IExtensionApplication.Terminate

 

    End Sub

 

    <CommandMethod("GetAlignmentStationLabelStyles")> _

    Public Sub cmdGetStationLabelStyles()

 

    End Sub

End Class

 

Now we need to first get the alignment object. Since both the API 101 Series and my AU class cover how to have the user select the alignment from a dialog box and/or graphically we are just going to grab the alignment object graphically. To interact with the user graphically we will need the current drawing’s editor. We get this with the following:

    Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor

Now that we have the editor, we can send an entity selection prompt to the editor for the user to be prompted with. Before we send the prompt, we need to set up the options of the prompt. We do this with a PromptEntityOptions object with is in the editor class.

Dim entSelOpts As New PromptEntityOptions(vbLf & _

 "Select alignment object or <exit>: ")

So we have a new object called “entSelOpts” which will prompt the user to select an alignment object. Let’s add a few additional options to our new object.

With entSelOpts

‘This will return none but if none is returned we will just exit the command

 .AllowNone = True

‘Since we are not manipulating the alignment we will allow objects on locked layer

 .AllowObjectOnLockedLayer = True

‘We have to set the message for a rejected object before we can define acceptable objects

 .SetRejectMessage(vbLf & "Object selected is not an aligment")

‘We want to only allow the user to select an alignment object

 .AddAllowedClass(GetType(Autodesk.Civil.Land.DatabaseServices.Alignment), True)

End With

Okay, so we have our prompt setup. Let’s use it to prompt the user. To get the prompt results, we use another object called a PromptEntityResult object. We use it in the following:

Dim entSelRes As PromptEntityResult = ed.GetEntity(entSelOpts)

If entSelRes.Status <> PromptStatus.OK Then Exit Sub

So the value of “entSelRes” is the result of prompting the user for an entity using the options we setup previously. Since this is a simple prompt, if anything besides Ok is returned we just exit  our command.

Ok, we should have our alignment object now. Let’s query it and get the alignment group labels. We have to use a transaction to get to this. To make sure I always properly dispose of my transactions, I create it with the “USING” function and then wrap the interior of the USING in a TRY…CATCH…END TRY for additional security. The alignment object is retrieved with the following:

Using db As Database = HostApplicationServices.WorkingDatabase

 Using trans As Transaction = db.TransactionManager.StartTransaction

  Try

   Dim align As Autodesk.Civil.Land.DatabaseServices.Alignment

   align = trans.GetObject(entSelRes.ObjectId, OpenMode.ForRead)     

  Catch

  End Try

 End Using

End Using

Inside the alignment object, is a method called “GetLabelGroupIds” which returns an ObjectIdCollection of all the label groups applied to this alignment. The ObjectId is actually NOT for the label style but for an object that represents the group settings for the label. For example, when you apply a label style that is a group label type, you also specify the range, increment (for station labels), geometry (for point type labels), etc. What is returned is this group object. Of course, each label type returns a different group type. So we need to track which label group type the ObjectId represents without crashing. We do this with the following:

Dim lblStaGroup As _

Autodesk.Civil.Land.DatabaseServices.AlignmentStationLabelGroup

Dim dbObj As DBObject

For Each lblId As ObjectId In lblIdCol

 dbObj = trans.GetObject(lblId, OpenMode.ForRead)

 If TypeOf (dbObj) Is _

Autodesk.Civil.Land.DatabaseServices.AlignmentStationLabelGroup Then

  lblStaGroup = DirectCast(dbObj, _

Autodesk.Civil.Land.DatabaseServices.AlignmentStationLabelGroup)

 End If

Next

Notice that we first take the ObjectId and apply it to a general database object. If the database object is the correct type (the AlignmentStationLabelGroup type) then we can go to work and cast the general object to the correct object type. Otherwise, just keep looping.

Next, let’s get the label style applied. We do this by finding the ObjectId for the label in the lblStaGroup object variable.

Dim lblStyle As Autodesk.Civil.DatabaseServices.Styles.LabelStyle

lblStyle = trans.GetObject(lblStaGroup.StyleId, OpenMode.ForRead)

Finally, we will write all this data out to the command line

ed.WriteMessage(vbLf & _

lblStaGroup.LabelType.ToString & " From Station: " & _

align.GetStationStringWithEquations(lblStaGroup.RangeStart) & _

" to Station: " & align.GetStationStringWithEquations(lblStaGroup.RangeEnd) & _

" | Style is " & lblStyle.Name)

We write it out to the command line using the method from the editor called WRITEMESSAGE. We write the label type (whether it is minor or major). Then we write the station range and we use a method built into the alignment object to provide us with a station formatted string of the station double. Lastly, we write out the label style’s name.

You can download the entire project source code here.

Conclusion

Feedback!! Was this exercise too simple? Too complex and hard?

What do you want to learn regarding Civil 3D .Net API?

3 comments

  1. I think you’ve hit the level right on the mark, took me about 3 days to get to the same point by poking, debugging, and using ADN resources.

    Thanks for your work!

  2. Partha Sarkar says:

    Very nice beginning Joshua !

    Good Luck !

    Partha Sarkar
    Autodesk

  3. john coon says:

    Joshua,

    Thanks, this is a great start for those of us learning dot net. lots to learn!

    Thank you for your efforts

    John