0% found this document useful (0 votes)
212 views67 pages

Streamlining Corridor Workflows With Dynamo For Civil 3D

Corridors are a crucial aspect of many Civil 3D models, but they can sometimes be time consuming to create, modify, and manage. This class will explore how Dynamo for Civil 3D can be used to improve efficiency in all aspects of corridor design and management. This class will cover workflows for corridor creation, corridor geometry manipulation, subassembly management, quantification, and style management. We’ll explore how to use the Python node to interact with corridors using the Civil 3D .NET

Uploaded by

Wagner Santos
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
212 views67 pages

Streamlining Corridor Workflows With Dynamo For Civil 3D

Corridors are a crucial aspect of many Civil 3D models, but they can sometimes be time consuming to create, modify, and manage. This class will explore how Dynamo for Civil 3D can be used to improve efficiency in all aspects of corridor design and management. This class will cover workflows for corridor creation, corridor geometry manipulation, subassembly management, quantification, and style management. We’ll explore how to use the Python node to interact with corridors using the Civil 3D .NET

Uploaded by

Wagner Santos
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 67

CES602153

Streamlining Corridor Workflows with Dynamo for


Civil 3D
Elliot Grubb
AtkinsRéalis

Learning Objectives

• Learn how to use Dynamo for Civil 3D to manipulate subassemblies and corridors.
• Learn how to use the Python node to interact with corridors using the Civil 3D .NET
API.
• Learn how to create corridor transitions with Dynamo for Civil 3D
• Discover workflows that improve efficiency when working with corridors.

Description
Corridors are a crucial aspect of many Civil 3D models, but they can sometimes be time
consuming to create, modify, and manage. This class will explore how Dynamo for Civil 3D can
be used to improve efficiency in all aspects of corridor design and management. This class will
cover workflows for corridor creation, corridor geometry manipulation, subassembly
management, quantification, and style management. We’ll explore how to use the Python node
to interact with corridors using the Civil 3D .NET API, expanding upon the functionality of
existing nodes. Learn how to best use Dynamo to streamline your workflows and processes
when working with corridors in Civil 3D.

Speaker(s)
As BIM Development Lead at AtkinsRealis, I bring expertise in information management, ISO
19650 standards and various software to the table. As a Civil 3D SME a large part of my role is
being responsible for Civil 3D, Infraworks & Navisworks standardization across our UK
transportation business being responsible for things like template production, standards,
guidance and training rollout. I believe in staying on the cutting-edge of technology, continually
seeking out new ways to drive process improvement. I've always been fascinated with the
power of technology and its ability to make a real difference in the world. I have a passion for
automating processes through Dynamo & .NET programming.
Before we begin

What is this class GOING to cover?

This class is going to focus on some very specific Dynamo for Civil 3D workflows around
corridors. The workflows I explore in this class are intended to allow you to become more
efficient in how you build and manage corridors and corridor code set styles. In doing so we will
cover some workflows around:

• Create baselines and corridors with Dynamo


• Create corridor transition sets with Dynamo, Python and the C3D .NET API
• Create & and control a “morphing” corridor transition with Dynamo
• Analyze corridor quantities via Dynamo & PowerBI
• Manage code set styles in Excel via Dynamo
What is this class NOT GOING to cover?

• Dynamo basics
• A full breakdown of the C3D & ACAD APIs
• Non-Corridor related Dynamo workflows
This class unfortunately won’t be covering Dynamo basics. It is assumed you already have a
basic understanding of Dynamo & Dynamo for Civil 3D. If you don’t, there are some fantastic AU
classes, The newly created Civil 3D Dynamo primer and of course the Dynamo forum.

• Dynamo primer - recently updated for Civil 3D! - Dynamo for Civil 3D - Dynamo
(dynamobim.org)
• Getting Started with Dynamo for Civil 3D: A Beginner’s Guide | Autodesk University
• Latest Civil3D topics - Dynamo (dynamobim.com)

Pre-Requisites

• All demonstrations conducted in C3D 2024.0, Dynamo Core 2.17.0.3472 & Dynamo for
Civil 3D 2.17.0.342
• Camber Package https://github.com/mzjensen/Camber
• Civil 3D Toolkit
Creating Corridors with Dynamo

Why create corridors using Dynamo?

Despite recent improvements in Civil 3D the default tools for corridor creation sometimes feel
clunky, particularly in scenarios where the creation of multiple corridors or baselines are
required in bulk. To create a baseline and corridor from a polyline or featureline using “out of the
box” Civil 3D the process requires a minimum of 20 clicks and 3 separate commands. We are
also unable to create multiple corridors at once. This can make corridor creation for kerbed
islands, car park (parking lots) kerbs, duct runs, barriers etc. time consuming. There is also
currently no support for adding multiple featurelines to a corridor as baselines.

So what are the use cases?

Whilst this workflow is not intended for modeling corridors that represent new sections of
highway with more complex geometry it is particularly useful for:

• Modelling kerbed islands, such as in a car park/parking lot or roundabout


• Ancillary items such as barriers, Ducts & trenches, ditches etc.
• Existing roads where “Fast” geometry is needed.
• Any other scenario where a corridor needs to be generated from a Featureline or
polyline
Graph inputs

Select polylines or featurelines to


create corridor(s) & baselines from

Prefix for name of alignments to be


created

Prefix for layer to place newly


created alignments

Style for newly created profiles

Style for newly created Alignments


ated
Alignments
Label style for newly created
alignments

Specifies whether multiple corridors should


be created or multiple baselines within one
corridor when multiple objects selected

Surface to create surface profile from

Corridor Name Prefix

Specifies whether surface profile should be


used or a profile createdby joining the start
and end elevations of surface profile

Assembly to use

Creating corridor baseline

The first step in creating our alignments that form our corridor baselines is to check
whether the selected objects are feature lines or polylines. If the objects selected are
Featurelines we create polylines from the featureline objects to allow us to create
alignments further downstream in our graph.

We use the Object.Type node to check if the object type of the selected object is a
polyline or a FeatureLine, If the object is a Featureline we obtain its Dynamo geometry
before creating polyline geometry in the DWG from the Dynamo polycurve. We then
obtain the object handle and use the DocumentExtensions.ObjectByHandle node to
convert the “Object” to a “Polyline”.

Should the selected object already be a polyline this is passed directly to the false input
of the If node.
Next, we can create alignments from the list of polylines from the output of the If node.
We utilize AlignmentExtensions.CreateAlignmentByPolyline. We also build our
alignment names and layer names using a series of code blocks and our input prefixes.
We then create a surface profile using the specified surface for the entire length of each
alignment using AlignmentExtensions.AddProfileBySurface. We construct the profile
name and layer name using the name of the alignment and some code blocks.
We then create a new profile linking the elevation at the start of the surface profile to the
elevation at the end of the surface profile. This is achieved by firstly creating an empty profile
using AlignmentExtensions.AddProfileByName then adding PVIs to the empty profile using
the start and end stations and elevations of the previously created surface profile.
Before the final step of creating corridors, adding baselines, and adding regions we
need to consider whether each Poyline/Featureline should be used to create a separate
corridor or if a single corridor is to be created with multiple baselines. When the Create
Multiple corridor Boolean input is set to true a list of unique strings is created to be used
as corridor names. This is done by counting the number of baselines then using the
range node and a code block to construct a corridor name based on the input prefix. In
a scenario where the multiple corridors Boolean is set to false a single corridor name is
passed through the If node.

Now the baselines have been created and our corridor name list constructed we can
create our corridors. The first step in this process if to use the If node to determine
which vertical baseline to use. When the Use Design Profile input is set to true the
profile which was created by joining the start and end elevations of the surface profile is
used. If the Use Design Profile input is set to false, the surface profile is used.

We then create an empty corridor using the CorridorExtensions.ByName node before


adding the baselines using CorridorExtensions.AddBaseline. If only one corridor is to
be created with multiple baselines the list lacing in the Add Baseline node ensures that
all the baselines are added to the single corridor.
After the corridor is created, we set the code set style using the
ObjectExtensions.SetParameterValueByName node to change the
CodeSetStyleName parameter to our specified code set style.

Finally, We use the CorridorExtensions.AddRegion node to add a region the length of


the entire baseline to the newly created corridors.
Creating Corridor Transitions with Dynamo

Corridor Transition Sets

With the 2023 of Civil 3D a new feature was introduced that allowed us to create transitions by
modifying subassembly parameters over station ranges. Ie. No need for targets or splitting of
regions. More information on the new corridor transition tool can be found at (1149) Model Civil
3D Corridor Transitions Using Any Subassembly - YouTube.

The 2024 release of Civil 3D then introduced an API for corridor transitions which in turn allows
us to interact with these objects using Dynamo.

Corridor Transitions with Dynamo – Use cases.

By creating these transition sets using Dynamo we can move towards designing certain features
with using only a series of inputs. Standard Dynamo graphs can be setup and deployed for
modelling things like:

• Dropped Kerbs / Curb ramps


• Widening – Bus stops laybys etc.
This can lead to greater consistency amongst teams and models by having Dynamo graphs
configured for local design standards.
E.g. In the UK dropped kerbs at pedestrian crossings typically have a 1:12 gradient dropped
kerb, and a minimum 1.2m dropped kerb/crossing width. The Dynamo graph could be
configured to create these features to standard requiring only the corridor station to insert the
transition as inputs to be utilized in the Dynamo player - All in one click!
Creating transition sets via the Python Node and C3D API.

When initially placing a Python node in Dynamo the following default boilerplate code is
contained in the node. This code provides us with a “template” for which we can create
our corridor transition.

• Lines 2, 3 & 4 are importing the Python engine, common language runtime and
traceback.
• Lines 7 – 12 are adding the AutoCAD and Civil 3D API reference to the common
language runtime – The yellow text are the names of the .dlls located in C:\Program
Files\Autodesk\AutoCAD 2024
• Lines 15 – 23 import the Autocad & Civil 3D namespaces
• Lines 28 & 29 are obtaining the active Civil 3D drawing and the active drawings editor
and storing these in their respective variables.
• In the above example we have also added a Try block at line 35 to handle errors. All
code within the try block will be monitored for exceptions (errors) if an error is
encountered the code inside the Except block at line 42 is executed, in this case that
means writing the error to the Python node output.
Once the relevant references are loaded, we can begin to create our code. We are firstly going
to assign the inputs we pass to the Python node to variables in our Python script as follows:

The IN Variable stores all the input to the python node. We can access and assign these values
to variables in our Python script using the index that corresponds to the input displayed on the
Python node.

Defining a Function

Next, we are going to define our CreateCorridorTransition function. By placing our core code
within a function, we are creating a re-usable block of code that performs a specific task, in this
case creating our corridor transition set. By utilizing a function, we can ensure our Python script
better handles list input.

When defining the function, we can also specify the parameters/arguments. These are values
we pass to the function when it’s called later in our code. Essentially these parameters allow us
to pass input data to the function which are then used inside the function.

Working inside a database transaction

Once the function is defined, we can move on to the contents of the function and our core code.
When we work with the Civil 3D or AutoCAD APIs we use the following workflow:
After obtaining the active document (which we stored earlier in the adoc variable) we lock the
document. Locking the document before making changes to the drawing database ensures that
no other changes to the database can be made whilst our code executes.
Opening a transaction is always recommended as it allows us to safely make changes to the
drawing database. Once we reach the bottom of our code we then commit the transaction and
any changes we made to the database in our transaction.
To lock the document, obtain the database and open the transaction we do the following (this is
also how the Python node boilerplate code is setup)

• Line 42 locks the document


• Line 43 obtains the drawing database and stores it in the db variable.
• Line 44 uses the database transaction manager to start the transaction and stores the
transaction in the t variable.
Unwrapping & accessing the corridor object

As we are passing the corridor to the Python node using the output of the Select Object
node we must first “unwrap” the corridor object. This is because the underlying API
corridor object is wrapped by the Dynamo object we see in the output of the Select
Object node.

If we were to use the Autodesk.Civil.DynamoNodes.Corridor object returned by the


Select Object node directly we would not be able to use any of the properties or
methods from the C3D/ACAD API that belong to the
Autodesk.Civil.DatabaseServices.Corridor object. Hence, we need to unwrap the
object to obtain the API corridor object!
Autodesk.Civil.DynamoNodes.Corridor

Autodesk.Civil.DatabaseServices.Corridor

To unwrap this object in Python we can use the InternalObjectId property. This allows
us to obtain the ObjectId of the underlying corridor in the drawing database. After
obtaining the corridors ObjectId we can then open the corridor object for write (we are
making changes to the corridor by introducing the transition) and store this in the corr
variable.

Stores the result Get object Gets the Opens the


in the corr method InternalObjectId corridor for
variable to unwrap write
Dynamo object

TOP TIP! – The InernalObjectId property can be used with a wide range of objects.
Not just corridors!
Creating the Transition Set

Now that we have obtained and opened the corridor API object we can create the
transition set as follows

• Line 49 obtains the first baseline in the corridor using the Corridor.Baselines Property
and stores it in the baselines variable. Note in this example the first baseline is obtained
for simplicity’s sake. In practice it is best to pass the desired baseline as an input
• Line 51 obtains the first baseline region in the baseline using the
Baseline.BaselineRegions Property and stores it in the blregion variable. Note in this
example the first baseline region is obtained for simplicity’s sake. In practice it is best to
pass the desired baseline region as an input
• Line 54 obtains any existing transitions associated with the baseline using the
Baseline.getTransitions Method and stores them in the exTransets variable
• Line 56 initializes a new variable called transet and sets its value to None
Next, we need to check if transition set with the specified name already exists. We do this by:
• Using a for loop we can iterate through the existing transition sets in the exTransets
variable. For each extranset in the exTransets list we:
1. Get the name of the current exTranset and store it in the exTransetName variable.
2. Checks if the exTransetName is equal to the name of the transition set we wish to
create stored in the transetname variable.
3. If the names match, We assign the exTranset to the transet variable and then break
out of the loop.
• On line 64 we can use an if statement that checks whether the transet variable is empty.
If the transet variable is empty this means no existing transition set with the specified
name exists and the transition set needs to be created
• On line 66 the transition set is then created using the CorridorTransitionSet Constructor
Constructor. We pass the name of the transition set, baseline region, subassembly name
and name type as parameters. The CorridorTransitionNameType.SubassemblyName
tells Civil 3D to use the subassembly name rather than subassembly class name.
Now that we have created the transition set, we need to add transition information to the
transition set, including, the subassembly parameter to transition, start and end stations, start
and end parameter values & the transition type. We can do this as follows:

• Line 68 initializes a new variable called transet and sets its value to None

• In line 71 we use the CorridorTransitionSet.AddTransition Method on the transition set


object which is stored in the transet variable. This allows us to add a transition to the
empty transition set. We pass the subassembly parameter name we wish to transition as
a parameter.

• The CorridorTransition object which we created on line 71 and assigned to the transinfo
variable has a series of read and write (get and set) properties listed in the API
documentation. Autodesk Civil 3D Help | CorridorTransition Class | Autodesk. By setting
these values we pass into our function we can form the transition geometry.

• We do this in lines 74 to 78 setting start station, end station, start value for the parameter
and end value for the subassembly parameter. We also specify the transition type to be
used in line 78. Ie. Linear, BayTaper, Parabolic etc.
Next, we need to apply the transition to the baseline and commit the transaction. We do so as
follows.

• In line 80 we create an empty list transets


• In line 83 we add the transition set to the list using the append method.
• In line 86 we use the Baseline.SetTransitions method on the baseline object we obtained
at the start of our function. We pass the transets list created in the previous line as a
parameter. This applies the transition information to the corridor.
• Finally, on line 88 we commit the transaction and set the function to return the name of
the newly created transition set.
But wait, how do we call our function?

To “use” our code we need to call the function we just created with the inputs we passed into the
Python node. This can be achieved with a simple while loop.

• Line 92 sets a variable i to 0 indicating the first position in a list.


• Line 93 calculates the number of items in the endstation list input to the python node and
stores that count in the noOfTrans variable.
• On line 94 we enter a loop that continues as long as i is less than noOfTrans
• On line 95 we call the CreateCorridorTransition function we defined passing the corridor,
transition set name, subassembly name, parameter name, start station, end station, start
value & end value – All inputs to the Python node we assigned to these variables earlier
in our script!
• The [i] on the station and parameter values tells python to use the item at a specified
index in the list. Each time the function is called 1 is added to i allowing the next item in
the list to be used.
The Python script can then be used in a Dynamo graph as follows:
The above example is created to allow modelling of dropped kerbs (curb ramps) compliant with
design standards. By selecting specific inputs the graph can be re-distributed amongst design
teams to create dropped kerbs using the Dynamo player. The only input the user needs to
specify is corridor, length, station, and transition lengths.
The transition can also be edited in a panorama window by selecting the corridor and selecting
“Edit Corridor Transitions” on the contextual ribbon. We can change all the transition parameters
such as stations, subassembly parameter values transition types etc. in this window.
Controlling a Morphing Subassembly Transition with Dynamo

What is the Morphing Subassembly?

The morphing subassembly is built on the concept of the Multi-Link-Transition subassembly


demonstrated by Jowenn Lua in his AU class AutoCAD Civil 3D and Subassembly Composer-
Real-World-Practice Tips and Tricks | Autodesk University. However, in our case the points are
created based on an offset from the subassembly origin, not the previous point. The morphing
subassembly is intended to provide you with another solution for modelling complex transitions
between subassembly shapes, it is particularly useful for kerbs, barriers etc. It is a versatile
subassembly that can be applied to a range of different shapes/subassemblies by changing the
parameters automatically with Dynamo. By using this subassembly, we don’t need to form
complex transition logic in our .PKT files – we can simply apply the morphing subassembly to a
region in our corridor.

How does the Morphing subassembly work?


The subassembly contains input parameters for initial and final X and Y values for each point in
the subassembly. The initial parameters used to construct the initial shape at the start of the
transition and the final parameters used to construct the final shape at the end of the transition.
We can then calculate the X and Y value of each point as it transitions over the region by using
the below expression inside a variable in subassembly composer:
x1i+(x1f-x1i)*(Baseline.Station-Baseline.RegionStart)/(Baseline.RegionEnd
Baseline.RegionStart)

• X1i – Input parameter for point 1 initial X offset.


• X1f – Input parameter for point 1 final X offset
This variable can then be used to create the point using a Delta X from origin. The process is
then repeated for the x and y values of each point.
The points are then connected with links to create a shape which can be used for corridor solids
extraction in Civil 3D.
The .PKT file of the morphing subassembly is included in the class materials for further
reference.
How can we use Dynamo to control this subassembly?
When we apply this subassembly in a corridor it is intended to form a transition between 2
regions in our corridor where different geometry exists in each of these 2 regions. To form the
initial shape in our morphing subassembly we would need to populate the initial offset input
parameters for each point in the morphing subassembly matching that of the shape in the
previous region.
Similarly, to form the final shape in our morphing subassembly we would need to populate the
final offset input parameters for each point in the morphing subassembly matching that of the
shape in the region after.
Doing this manually becomes quite time consuming – particularly if your project contains
bespoke geometry.
We can use Dynamo to read these values from the previous region and region after and
populate our morphing subassembly parameters automatically!
The process is as follows:
1. Insert region with morphing subassembly
2. Read X and Y offset to each point in specified applied subassembly at the last station of
the region before the transition.
3. Populate the initial X and Y input parameters in the morphing subassembly using the
values obtained in step 1 to form the initial shape.
4. Read X and Y offset to each point in specified applied subassembly at the first station of
the region after the transition.
5. Populate the final X and Y input parameters in the morphing subassembly using the
values obtained in step 5 to form the final shape.
6. Rebuild the corridor to create the transition geometry.
How do we achieve this in Dynamo?

The graph requires 6 inputs:

• Corridor
• Name of the transition region (containing the morphing subassembly)
• Baseline name
• Name of the subassembly we wish to transition from (initial shape)
• Name of the subassembly we wish to transition to (final shape)
• Name of the Assembly containing the morphing subassembly
• Name of the Morphing subassembly
We then obtain the assembly and morphing subassembly by name and clean the list. Which
then allows us to initially set all the parameters to zero to ensure all values are overwritten
further downstream in our graph. We do this using the
Subassembly.SetParamaterValueByName node, constructing a list of our parameter names in
a code block.

Reading The Values For the Morphing Subassembly Input Parameters via Python
Now that we have completed the necessary preparation in our Dynamo graph we can read the
offsets to each point in the necessary applied subassembly in the regions before and after our
transition. We do this by obtaining the applied subassembly from the applied assembly at the
relevant station in the corridor (last station of region for initial shape, first station of region for
final shape).
Once we obtain the appliedsubassembly we use the AppliedSubassembly.Points Property to
obtain the collection of points belonging to the subassembly.
We can then iterate through the points and use the
CalculatedPoint.StationOffsetElevationToSubassembly Property. This returns the x offset as the
Y component of the point returned by the property and the y offset as the z component returned
by the property. The reason for the misalignment between the value and the point component
which stores the value is due to the x component of the returned point being used for the station
of the point relative to the baseline – think of the point returned by this property as simply being
a placeholder for 3 different values and not point coordinates.
The first step is to assign our inputs to variables and initialize our lists.
• Lines 26 to 30 assign the input to the python node, including corridor, baseline region
name, initially and final subassembly names and the baseline name to variables
• Lines 31 to 34 initialize empty list variables to store our output
• Lines 37 & 38 obtain the active DWG and the document editor

• Line 40 locks the document to only allow input from our script.
• Line 41 obtains the drawing database.
• Line 42 starts a transaction.
• Line 45 unwraps the Dynamo corridor object obtaining the underlying ObjectId before
opening the corridor object for write and assigning it to the corr variable.
• Lines 46 obtains the baselines associated with the corridor using the Corridor.Baselines
Property. We can then obtain a specific baseline in the collection of baselines returned
by this property using the square brackets. We use the blName variable inside these
square brackets to obtain the baseline in the collection with the specified name.
• Line 46 then obtain the BaselineRegions associated with the specified baseline.
• Line 48 then counts the number of baseline regions in the collection.
• Line 49 uses an if statement to check if the number of baseline regions is greater than 0.
If there are no baseline regions the else statement on line 61 tells the script to output
“No regions in baseline” in line 62.
• Line 51 initiates a loop using the for keyword to iterate through the collection of
baselineregions. It uses the enumerate function to keep track of the iteration by
assigning the index to i and the baseline region to blr in each iteration.
• Line 52 checks if the current baseline region's name matches the name of the transition
region.
• If a match is found, line 54 stores the matching baseline region in the blregiontrans
variable.
• Line 55 stores the loop index in the index variable.
• Line 57 attempts to get the baseline region before the transition region (blrbefore) if the
current index is greater than 0.
• Line 59 attempts to get the baseline region after the transition region (blrafter) if the
current index is less than the total number of baseline regions minus 1.
• On Line 60 the loop breaks when a match is found, and the desired baseline regions are
obtained.

Now that we have obtain the relevant baseline regions, we can get the applied subassembly
at the last station of the region containing the shape we wish to transition from and calculate
the offset to each point on the subassembly.
• Line 66 obtains the collection of applied assemblies in the region before the transition
region using BaselineRegion.AppliedAssemblies Property and assigns it to the variable
AppliedAssembliesFirst
• Line 67 counts the number of items in the AppliedAssembliesFirst collection and
stores the count in the variable AppliedAssembliesFirstCount.
• Line 69 checks if there are applied assemblies in the region before the transition. If
AppliedAssembliesFirstCount is greater than 0, it proceeds to retrieve the last applied
assembly. If not, it sets the OUT variable to "No applied assembly in baseline region."
• Line 76 gets the applied subassemblies at the last applied assembly using
AppliedAssembly.GetAppliedSubassemblies Method and assigns them to the variable
AppSubassembliesLast.
• Line 78 initializes a loop that iterates through the AppSubassembliesLast collection to
search for a specific subassembly with the name initSaName. It does this by opening
each applied subassembly In the collection for read and checking its name property. If
the name matches the initial subassembly name It sets the variable
Appliedsubassembly to the found subassembly.
• Line 88 retrieves the points of the applied subassembly (Appliedsubassembly) and
stores them in the sapointsbefore variable.
• In Lines 90-93 A loop iterates through sapointsbefore and extracts the x offset (y
component) and y offset (z component) from the subassembly insertion to each
subassembly point using CalculatedPoint.StationOffsetElevationToSubassembly
Property. These values are appended to the lists sapointsoffsetinitialx and
sapointsoffsetinitialy. A dictionary initdict is then constructed, which stores the x and y
offset to each point in the subassembly.
This process is also repeated for the region after the transition region. Ie. The region
containing the final shape geometry we wish to transition to.

• Line 96 obtains the collection of applied assemblies in the region after the transition
region using BaselineRegion.AppliedAssemblies Property and assigns it to the variable
AppliedAssembliesAfter
• Line 97 counts the number of items in the AppliedAssembliesAfter collection and
stores the count in the variable AppliedAssembliesAfterCount.
• Line 99 checks if there are applied assemblies in the region after the transition. If
AppliedAssembliesAfterCount is greater than 0, it proceeds to retrieve the first applied
assembly. If not, it sets the OUT variable to "No applied assembly in baseline region."
• Line 105 gets the applied subassemblies at the first applied assembly using
AppliedAssembly.GetAppliedSubassemblies and assigns them to the variable
AppSubassembliesFirst.
• Line 107 initializes a loop that iterates through the AppSubassembliesFirst collection to
search for a specific subassembly with the name finalSaName. It does this by opening
each applied subassembly In the collection for read and checking its name property. If
the name matches the initial subassembly name It sets the variable
Appliedsubassembly to the found subassembly.
• Line 117 retrieves the points of the applied subassembly (Appliedsubassembly) and
stores them in the sapointsafter variable.
• In Lines 118-121 A loop iterates through sapointsafter and extracts the x offset (y
component) and y offset (z component) from the subassembly insertion to each
subassembly point using CalculatedPoint.StationOffsetElevationToSubassembly
Property . These values are appended to the lists sapointsoffsetfinalx and
sapointsoffsetfinaly. A dictionary finaldict is then constructed, which stores the x and y
offset to each point in the subassembly.

• Finally, the transaction is committed and the 2 dictionaries containing the offsets to each
point are assigned to the Python node output

The order of the offsets is in the same order as the subassembly points eg. P1, P2,
P3…P10… Bear this in mind if you intend to use this with custom subassemblies.

Once we have obtained our values using Python, we can clean up the data in our Dynamo
graph.
The Dictionary.ValueAtKey node is used to obtain separate lists of X and Y offsets for both
the start and end shape of the transition. Because the subassembly is on the left side the X
outputs are negative values. As the morphing subassembly parameters expect a positive
value me multiple each item in the list by -1.
Finally, we se the parameters on the morphing subassembly using the
Subassembly.SetParameterValueByName node. Passing the names of the morphing
subassembly parameters and the parameter values from the previous nodes.
Note that both lists are counted. This is to deal with scenarios where the initial and final
subassemblies may have a different number of points. In this case we transition from a shape
with 8 points to 6 points. This means we must drop the final 2 parameter names from the
parameter name list to prevent unexpected behavior.
After the parameter values have been set the corridor can be rebuilt manually or by using the
Corridor.Rebuild node to create the transition geometry in our corridor!
Extracting & Visualizing Corridor Quantities with Dynamo & PowerBI

Dynamo is not only useful for creating and manipulating Civil 3D objects but is an extremely
useful tool for obtaining data from Civil 3D models efficiently. The data we can extract using
Dynamo for Civil 3D can be extremely useful for a multitude of downstream activities. In this
example we will focus on extracting and using that data to visualize our corridor quantities in
PowerBI.

Why use Dynamo?


The major advantage of using Dynamo is the fact we do not need to setup QTO, Assign Pay
Items, materials or create sample lines etc. All the data we extract comes directly from our
corridor and makes use of point, link and shape codes defined in our custom subassemblies.

How do we do it?
In the above dashboard all the visualizations are produced by consuming an Excel report
produced by Dynamo.

The dashboard makes use of 4 key pieces of data:


• FeatureLine lengths – allowing us to display lengths of linear features in our corridor
such as lengths of different kerb types.
• Shape Volumes – allowing us to quantify and visualize the pavement makeup of our
corridor. Eg. Volume of surface course, Sub base etc. as well as pavement types by
volume.
• Link Slopes – To visualize crossfall (cross slope) of the lanes in our corridor.
• Corridor surface & Volume Surface – For basic cut & fill visuals.

Making full use of custom subassembly codes and code set styles
To extract as much data as possible from our corridors the value of point, link & shape codes
and how we define these in our custom subassemblies should not be underestimated!

Shape Codes
When defining shape codes in my custom pavement subassembly I make heavy use of input
parameters to derive the shape codes for each pavement layer. This allows us to incorporate
pavement course, pavement type & pavement PSV into our shape codes – Which becomes
extremely useful for quantifying pavement volumes of each course, type & PSV downstream!

The above image shows how input parameters can be utilized to apply a level of automation to
our subassembly shape codes.
Point Codes
Similarly kerb types are applied to the kerb point code to allow us to obtain lengths of different
kerb types downstream from the coded corridor featureline.

Output Parameters for Link Slopes


To extract lane slopes (or slope on any link in any subassembly) we make use of an output
parameter in a custom subassembly. This is defined in subassembly composer by assigning the
slope of our pavement surface link to the OutCrossfall output parameter. This allows us to read
the value of the output parameter on the applied subassembly at each corridor station to obtain
lane crossfall values.
Extracting the Data in Dynamo
Now that we have setup our subassemblies to support quantity extraction, we proceed to create
our quantity reports using Dynamo.
The only inputs required are the corridor to report and the baseline to report lane crossfall.

We then obtain all codes in the corridor using Corridor.Codes

Calculating Featureline Lengths for Each Point Code


• Obtain corridor featurelines for each point code
• Create Dynamo polycurve geometry for each featureline
• Get the curves that make up each polycurve
• Obtain the sum of the lengths of each curve within each polycurve
• Get the sum of length of polycurves for each point code.
• Create a dictionary storing the point code and total feature line length in the corridor.

Getting the Volume of Each Solid for Each Shape Code


• Get the corridor solids for each shape code using Corridor.GetSolids (these must
already be extracted)
• Obtain the dynamo geometry of the solids.
• Get the volume of each solid before creating a dictionary of the solid volume for each
shape code in the corridor
Getting Lane Crossfalls (Cross slopes)
• Get the subassemblies applied in the corridor at each assembly insertion.

• We then filter the list of applied subassemblies to only include a specified subassembly.
In this case “ATK_Pavement”
• We then separate left and right sided subassemblies into separate lists

• We then filter the parameters to obtain the value of the crossfall output parameter before
multiplying the values by 100 to obtain a slope %.
Exporting the Data to Excel
After we have extracted all the necessary data from our corridors, we can tidy the data and use
the Data.ExportToExcel node to write the data to Excel. In the graph the Overwrite parameter
is set to true. This ensures that any existing data in the Excel output is removed to avoid
skewing the PowerBI visuals.
It’s also important to note that because we are overwriting the data the heading of each column
needs to be added to the lists using the List.AddItemToFront nodes.
This process is repeated for the featureline lengths, shape volumes, and cut and fill volumes.
Excel Output
Once the data is exported it is contained within 4 separate sheets. Featurelines, Shapes,
Surface Volumes & Lane slope.
Visualising the Data in PowerBi
We can then start to transform this data in the transform data window in PowerBI. In the below
example we run through the steps organize the data to produce a visual detailing pavement
make up volumes.
Visualize More Data!
In this example we have only scratched the surface in terms of what data we can extract using
Dynamo and visualize with PowerBI. Use your own models to extract the likes of offsets to
FeatureLines, Number of corridor sections, Style info, surface points – The list goes on!
Managing Corridor Code Set Styles with Dynamo

Why Manage Code Set Styles with Dynamo?


Code set styles can be time consuming to create, manage, sort and maintain when using the
out of the box tools in Civil 3D. The default edit code set style window lacks functionality to sort,
filter & import from external sources such as Excel or different DWGs. Although we do have the
ability to import codes from subassemblies this can still become time consuming – particularly
when dealing with subassemblies where codes are controlled by multiple input parameters
leading to multiple different code combinations – The subassemblies driving the corridor
quantification in this class are a great example of this!

The missing filter, sort & import functionality I have just described may not seem that beneficial
initially. But in times where efficiency is everything, we want to utilize code set styles to
automate corridor display for downstream tasks such as drawing production, setting out, GIS
extraction etc. Essentially ensuring our corridors are driving all our outputs eliminating the need
to export separate xrefs.
To accomplish this, templates tend to require a lot of subassembly codes and code set styles.
My Civil 3D template currently in use in our UK Highways business contains over 600 codes in
each code set style across 19 code set styles. It’s when dealing with these codes set styles
that having the ability to bulk import, sort & filter becomes extremely useful.
Combining Dynamo & Excel to Make Code Set Styles More Manageable
By utilizing Dynamo we can write our code set styles to Excel, Make any necessary
amendments such as adding codes or changing styles and descriptions before reading the
updated code set style back into our DWG. This also means we can keep up to date records of
exactly what our code set styles are doing. The high-level process is as follows:

By combining the Style nodes in the camber package and some brief Python we can make the
above possible. We use 2 Dynamo graphs – One to write code set styles & the other to read
code set style info back into the DWG.

Writing Code Set Style to Excel


The only input the graph requires is to set the code set style to export. We then obtain each
code set style item and the type – Point, Link or shape.

We can then filter to obtain point codes (Marker type) by using the String.Contains node and
filtering the list by the returned Boolean variables. This then allows us to obtain each code, it’s
description, code style, label style, feature line style name, pay items and classification.
We can then write this data to a “Point” sheet in Excel.
We repeat this process for link codes writing these to a “Link” sheet.

And similarly for shape codes


Making Changes to the Code Set Style in Excel
After running the write script the code set style is written to Excel with Point, link and shape
codes written to a separate sheet.

I can not only use this Excel sheet to quickly search and sort my code set style but any number
of codes can be added, added or amended. In this scenario I have added 2-point codes and set
their styles and descriptions. I have also changed the styles of 2 existing codes.
Reading Code Set Style Changes Back into Civil 3D
After making the necessary changes we can use the read code set styles graph to update the
code set style in Civil 3D.
We first read the Point codes and obtain each code and its styles, description etc.

We then add any new codes to the code set style setting a default marker style. We then use
[passthrough,waitfor][0] inside a code block. This tells Dynamo to wait for the output of the
CodeSetStyle.AddPointItemNode before passing through the code set style to the rest of the
graph. This ensures that any new codes are added before we attempt to change their styles.
We then filter out any codes that are not present in the Excel input.
The passthrough,waitfor code block is then utilized again to wait for the output of the
List.Flatten node before setting Desription, Label Style & pay items. Errors in these nodes are
expected for blank items as these will return null. However, any non-blank items will be set as
intended.

To set the featureline style we need to get the FeaturelineStyle API Object. We do this using a
short Python script.
• Lines 26-28 assigns the input to the python node(code set style name, Code, Feature
line style name) to variables.
• Line 29 initializes the output variable
• Line 38 obtains the code set style collection in the current document and iterates through
each id in the code set style collection
• Line 40 opens the code set style for write
• Line 42 obtains the code set style name
• Line 44 uses an if statement to find the code set style with the same name as the
specified input.
• Line 46 gets the item in the code set style by it’s code and stores it in the cssitem
variable using the CodeSetStyle.GetItemBy.
• Line 48 Sets the featureline style to the featureline style with the specified name.
• Line 49 appends the code set style item to the output list.
The marker style is also set using a short Python script. The python logic is the same as
setting the feature line style except the CodeStyleName property on line 48 is used to set
the marker style.

Setting Link and Shape Styles


The above process is then repeated for link and shape codes. Python is used in those cases to
set only the link and shape style. Full examples can be found in the Dynamo graph contained in
the class materials.
References & Other Stuff

Packages
• Camber (with thanks to Zachri Jensen) - GitHub - mzjensen/Camber: An open-source
Dynamo package for Civil 3D.
• Civil 3D Toolkit
• Monocle – useful for tidying graphs etc.

Other resources
 The Dynamo primer – Recently updated for Civil 3D! Dynamo for Civil 3D - Dynamo
(dynamobim.org)
 Dynamo Forum Latest Civil3D topics - Dynamo (dynamobim.com)
 Civil 3D API Documentation Autodesk Civil 3D Help | Autodesk.Civil.DatabaseServices
Namespace | Autodesk

Multi-Link Transition Subassembly


As described in my handout the “Morhping Subassembly” is an evolution of the MLT transition
subassembly created by Jowenn Lua in his AU class:
 AutoCAD Civil 3D and Subassembly Composer-Real-World-Practice Tips and Tricks |
Autodesk University

Code set Style Automation


Subassembly codes and code set styles play a huge part in visualizing corridor quantities using
the methods described in this class. Should you wish to learn more about getting the most out of
code set styles I highly recommend my colleagues class: Automation opportunities hiding inside
Civil3D since the early 2000’s | Autodesk University

Corridor Transitions
More information on the new corridor transition feature that was introduced into Civil 3D 2023
and utilized in this class can be found at Model Civil 3D Corridor Transitions Using Any
Subassembly - YouTube & Autodesk Civil 3D Help | About Corridor Transitions | Autodesk

Contact Me
 LinkedIn - Elliot Grubb | LinkedIn
 Email – [email protected]

You might also like